辞書型の戻り値の記述について


以下に示す、戻り値に関する記述の意味が分かりません。

[code]

    return {k: v for k, v in balance.items()
            if isinstance(v, str) and float(v)}
    
[/code]

リスト内包表記を参考に、自分なりに、以下の記述と同等表現と考えたのですが合ってますか。

[code]

    return{}
    for k, v in balance.item():
        if (isinstance(v, str) and float(v)):
           .setdefault(k, v) 
    
[/code]

コードの全体像は下記のとおりです。

[code]

    def balance(self):
        endpoint = self.url + '/api/accounts/balance'
        return self._request(endpoint=endpoint)
    
    @property
        def position(self):
        balance = self.balance()
        return {k: v for k, v in balance.items()
                if isinstance(v, str) and float(v)}
    
[/code]

※上記コードは [#12 Python×ビットコイン自動売買 | クラスを作成してコードを読みやすくしよう！](https://tech-
diary.net/create-coincheck-class-object/) で紹介されているコードです。




> リスト内包表記を参考に、自分なりに、以下の記述と同等表現と考えたのですが合ってますか。

実際に実行してみると判りますが、`.setdefault(k, v)` の部分で syntax error になります。syntax error
を修正したとしても、最初に `return{}` としてしまっているので `Coincheck.position` property は常に empty
dict(空(カラ)の辞書)を返す事になります。

以下は動作チェック用の stub code になります。

[code]

    if __name__ == '__main__':
      import json
      from pprint import pprint
    
      cc = Coincheck('a', 'b')
    
      # 取引所APIドキュメント|仮想通貨取引所のCoincheck(コインチェック)
      # https://coincheck.com/ja/documents/exchange/api#account-balance
      cc.balance = lambda: json.loads('''
        {
          "success": true,
          "jpy": "0.8401",
          "btc": "7.75052654",
          "jpy_reserved": "3000.0",
          "btc_reserved": "3.5002",
          "jpy_lend_in_use": "0",
          "btc_lend_in_use": "0.3",
          "jpy_lent": "0",
          "btc_lent": "1.2",
          "jpy_debt": "0",
          "btc_debt": "0"
        }''')
    
      print('Original:')  
      pprint(cc.position)
    
      # replace Coincheck.position property
      def myposition(self):
        balance = self.balance()
        dic = {}
        for k, v in balance.items():
          if isinstance(v, str):
            try:
              if float(v): dic[k] = v
            except ValueError:
              continue
    
        return dic
      
      Coincheck.position = property(myposition)
    
      print('Replaced:')  
      pprint(cc.position)
    
    # 実行結果
    Original:
    {'btc': '7.75052654',
     'btc_lend_in_use': '0.3',
     'btc_lent': '1.2',
     'btc_reserved': '3.5002',
     'jpy': '0.8401',
     'jpy_reserved': '3000.0'}
    
    Replaced:
    {'btc': '7.75052654',
     'btc_lend_in_use': '0.3',
     'btc_lent': '1.2',
     'btc_reserved': '3.5002',
     'jpy': '0.8401',
     'jpy_reserved': '3000.0'}
    
[/code]

例外処理を行っているのは、`float()` は `ValueError` を発生させる場合があるからです。例えば、

[code]

      cc.balance = lambda: {
        'a': '1.0', 'b': '2.0', 'c': '3.0c', 'd': 4.0
      }
    
[/code]

として元のコードを実行すると、以下の様にエラーが発生します。

[code]

    Traceback (most recent call last):
      File "coin_check.py", line 74, in <module>
        print(f'Original: {cc.position}')
      File "coin_check.py", line 61, in position
        return {k: v for k, v in balance.items()
      File "coin_check.py", line 62, in <dictcomp>
        if isinstance(v, str) and float(v)}
    ValueError: could not convert string to float: '3.0c'
    
[/code]

※ API ドキュメントを読む限り `ValueError` が発生する事はなさそうなので上記の例外処理は不要かもしれません。

