質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1279閲覧

Python ソースコードの意味について

raspypy

総合スコア247

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/06/26 12:56

##分からないこと

次のサイトに掲載されているソースコードを使おうとしていますが,
https://github.com/AmbientDataInc/LoRa-rssi-measure/blob/master/RPi3/lora.py
あらかじめソースコードの意味を理解しようとしています.

どうしても分からない部分があり,教えていただけると助かります.

##プログラム

python

1# ソフトシリアル経由でLoRaモジュールを読む 2 3import serial 4import RPi.GPIO as GPIO 5import struct 6import time 7 8ResetPin = 12 9 10class LoRa(): 11 def __init__(self): 12 GPIO.setmode(GPIO.BOARD) 13 GPIO.setwarnings(False) 14 GPIO.setup(ResetPin, GPIO.OUT) 15 GPIO.output(ResetPin, 1) 16 17 self.s = serial.Serial('/dev/serial0', 115200) # シリアルポートを115200kbps, 8bit, Non parity, 1 stop-bitでオープン 18 19 def reset(self): 20 GPIO.output(ResetPin, 0) 21 time.sleep(0.1) 22 GPIO.output(ResetPin, 1) 23 24 def open(self): 25 self.s.open() 26 27 def close(self): 28 self.s.close() 29 30 def readline(self, timeout = None): 31 if timeout != None: 32 self.s.close() 33 self.s.timeout = timeout 34 self.s.open() 35 line = self.s.readline() 36 if timeout != None: 37 self.s.close() 38 self.s.timeout = None 39 self.s.open() 40 return line 41 42 def write(self, msg): 43 self.s.write(msg.encode('utf-8')) 44 45 def parse(self, line): 46 fmt = '4s4s4s' + str(len(line) - 14) + 'sxx' 47 data = struct.unpack(fmt, line) 48 hex2i = lambda x: int(x, 16) if int(x, 16) <= 0x7fff else ~ (0xffff - int(x, 16)) + 1 49 rssi = hex2i(data[0]) 50 panid = hex2i(data[1]) 51 srcid = hex2i(data[2]) 52 msg = data[3].decode('utf-8') 53 return (rssi, panid, srcid, msg) 54 55def main(): 56 lr = LoRa() 57 while True: 58 data = lr.parse(lr.readline()) 59 print(data) 60 61if __name__ == "__main__": 62 main()

46行目
47行目において,フォーマット文字列 fmt に従い値 lineをパックして、文字列で返しているので,
そのフォーマットを指定しているのが46行目なのですが,'4s4s4s'と'sxx'の意味が分かりません.

48行目
変数xについてlambda式を定義していると思うのですが,lambda式の意味が理解できていません.

教えていただけると助かります.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

46行目
47行目において,フォーマット文字列 fmt に従い値 lineをパックして、文字列で返しているので,
そのフォーマットを指定しているのが46行目なのですが,'4s4s4s'と'sxx'の意味が分かりません.

公式ドキュメントを確認しましょう。
7.3. struct --- 文字列データをパックされたバイナリデータとして解釈する — Python 2.7.18 ドキュメント

48行目
変数xについてlambda式を定義していると思うのですが,lambda式の意味が理解できていません.

hex2i = lambda x: int(x, 16) if int(x, 16) <= 0x7fff else ~ (0xffff - int(x, 16)) + 1

これは渡された4桁の16進数("0000"~"ffff")を、int型の数値に変換するラムダ式です。
渡された文字列が0x7fff以下かそうでないかで処理を分けている理由は、渡される4桁の16進数がマイナスの数値を「1の補数」で表現しているからです。
数値を表現する方法の詳細は割愛しますが、大雑把に言うと0x0000~0x7fffはそのままプラスの数値、0x8000~0xffffはマイナスの数値(0xffffが0、0xfffeが-1、0xfffdが-2、0xfffcが-3……)として解釈しています。
もし詳細な方法を理解したいのであれば「1の補数」や「2の補数」で検索してみてください。

投稿2021/06/26 14:34

編集2021/06/26 14:38
ku__ra__ge

総合スコア4524

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

raspypy

2021/06/26 14:45

詳しい解説をありがとうございます. 48行目についてはよく理解することができました. 46行目の理解を確認するため,実際のデータを確認しました. '4s4s4s'の部分は,確かにデータの頭に12Byteの文字列が付加されていました. str(len(line) - 14) の部分は,読み取ったデータ(line)の文字数から14を引いた値で,データ長を意味していると考えています.(デバイスの仕様をみて調べます) ここまで理解できたのですが,最後の'sxx'がよく分かりません. 度々申し訳ございませんが,教えていただけると助かります.
ku__ra__ge

2021/06/26 15:04 編集

公式ドキュメントには以下のようにあります。 > count の指定がない場合のデフォルトは 1 です。 文字列1バイトとパディングバイト2つではないでしょうか?
YT0014

2021/06/26 15:18

切る場所が間違っているかと。 str(len(line) - 14)は、sxxの最初のsとセットで、msg用の文字列を指定。 xxで、最後の2文字を捨てるという指定です。
raspypy

2021/06/26 15:24

コメントありがとうございます。 実際のデータと照らし合わせて確認していたのですが,どうしても'sxx'の部分が理解できませんでした. 次の理解で正しいでしょうか? '4s4s4s'は,ヘッダー部分の12byte (実際のデータにも12Byte分のヘッダーが付加されていました) 続いて, str(len(line) - 14)+'sxx'の部分は, str(len(line) - 14)分の文字列データ(s)と,CRLF(xx: 2バイト分)である. CRLFは文字列データとは無関係なので,捨てる.ということでしょうか?
YT0014

2021/06/26 15:32

4s4s4sNsxx、ただし、Nはlen(line) - 14とすれば、理解できますか? 4項目で、最後の2バイトを捨てるというコードなのは確かですが、前提条件などは未確認なので、実際のデータをご提示いただいても、正否の判定はしかねます。
raspypy

2021/06/26 15:40

良く理解できました.ありがとうございました。
guest

0

  • 46行目

公式マニュアルル struct --- 書式文字列

をお読みください。

  • 48行目

hex2i = lambda x: int(x, 16) if int(x, 16) <= 0x7fff else ~ (0xffff - int(x, 16)) + 1

これは、

python

1def hex21(x): 2 return int(x, 16) if int(x, 16) <= 0x7fff else ~ (0xffff - int(x, 16)) + 1

と同じです。以下でも同じです。

python

1def hex21(x): 2 if int(x, 16) <= 0x7fff: 3 return int(x, 16) 4 else: 5 return ~ (0xffff - int(x, 16)) + 1

投稿2021/06/26 14:05

ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問