【问题标题】:What is the correct way to check an object's type in a conditional statement - python在条件语句中检查对象类型的正确方法是什么 - python
【发布时间】:2018-12-09 09:24:51
【问题描述】:

在条件语句中检查对象类型的正确方法是什么?

编辑:看来我误诊了这个问题。我的条件语句没有触发,因为 json.dumps 代码没有像我想象的那样工作。尽管错误消息说o.__class__.nameint64,但在引发错误之前它实际上从未具有该值(我通过逐步调试进行了检查)。它是如何工作的,我不太清楚,是另一天的主题。我会在下面回答这个问题。

我可以按照下面 Lenik 的建议解决我遇到的问题。

背景:

执行时

from json import dumps
json.dumps(vars(my_object))

我收到一个错误

File "C:\ProgramData\Anaconda3\lib\json\encoder.py", line 180, in 
  default    o.__class__.__name__)
TypeError: Object of type 'int64' is not JSON serializable

在 python 中使用json.dumps 时出错,在运行代码后我使用vars 语句将一些对象转换为字典。

我得出结论,在对象的某个地方我使用的是 numpy int64 而不是标准的 python int,这是导致错误的原因。

问题是 my_object 有很多层和要查看的地方。

所以我认为聪明的做法是在C:\ProgramData\Anaconda3\lib\json\encoder.py 的第 180 行放置一个条件断点(我可以在 PyCharm 中执行此操作),条件为

 o.__class__.__name__ == "int64"

然后我可以在调试模式下运行代码,并希望找到有问题的层/变量。

我已经尝试过了,以及在我的 dumps 调用和调用堆栈中的最低点之间的几个调用堆栈中,但我的断点从未被触发。

因此我怀疑我没有使用正确的条件语句来检查正在序列化的对象的名称...?

因此我的问题是: 在条件语句中检查对象类型的正确方法是什么?

这是导致问题的对象:

[  
   {  
      "combat_id":null,
      "units":[  
         {  
            "unit_id":7,
            "engagements":{  
               "front":[  
                  8,
                  -20,
                  -20
               ],
               "left":[  

               ],
               "right":[  

               ],
               "rear":[  

               ]
            }
         },
         {  
            "unit_id":8,
            "engagements":{  
               "front":[  
                  7,
                  -20,
                  80
               ],
               "left":[  

               ],
               "right":[  

               ],
               "rear":[  

               ]
            }
         }
      ],
      "combat_log":{  
         "combat_id":null,
         "full_log":[  
            [  
               {  
                  "initiative_step":"asf",
                  "_load_printables":true,
                  "striker_names":[  
                     "Pieka's Spear Boys",
                     "Coert's Pennyless Pokers"
                  ],
                  "striker_descs":[  
                     "High Elf Core Infantry",
                     "High Elf Core Infantry"
                  ],
                  "striker_players":[  
                     "Pieka",
                     "Coert"
                  ],
                  "striker_qtys":[  
                     25,
                     21
                  ],
                  "target_names":[  
                     "Coert's Pennyless Pokers",
                     "Pieka's Spear Boys"
                  ],
                  "target_descs":[  
                     "High Elf Core Infantry",
                     "High Elf Core Infantry"
                  ],
                  "target_players":[  
                     "Coert",
                     "Pieka"
                  ],
                  "target_qtys":[  
                     21,
                     25
                  ],
                  "attack_types":[  
                     "melee",
                     "melee"
                  ],
                  "attacks":[  
                     20,
                     21
                  ],
                  "to_hit_dcs":[  
                     4,
                     4
                  ],
                  "hits":[  
                     10,
                     10
                  ],
                  "to_wound_dcs":[  
                     4,
                     4
                  ],
                  "savable_wounds":[  
                     5,
                     5
                  ],
                  "armor_dcs":[  
                     5,
                     5
                  ],
                  "armor_saves":[  
                     1,
                     1
                  ],
                  "ward_dcs":[  
                     7,
                     7
                  ],
                  "ward_saves":[  
                     0,
                     0
                  ],
                  "unsaved_wounds":[  
                     4,
                     4
                  ],
                  "remaining_wounds":[  
                     17,
                     21
                  ],
                  "input":[  
                     ""
                  ],
                  "printables":[  
                     "<dominus_core.objects.sub_classes.combat.init_step_log.PrintableEntry object at 0x000000000EA72B70>",
                     "<dominus_core.objects.sub_classes.combat.init_step_log.PrintableEntry object at 0x000000000EA92C88>"
                  ],
                  "printable_strings":[  

                  ],
                  "longest_name":1,
                  "_longest_name":28
               }
            ]
         ],
         "easy_log":[  

         ]
      }
   }
]

【问题讨论】:

  • 尝试type(variable) 会返回类型
  • 感谢@KostadinSlavov。我试过type(o) == int64,但这也没有触发断点。
  • 给我看看你的对象
  • @KostadinSlavov,好的,我将它添加到 OP 中。可能是非序列化的PrintableEntry 对象(靠近底部)导致了疼痛。由于我们已经建立了两种测试类型的方法(但它们并没有解决我的问题),所以我也将改变问题的角度。
  • 好的,等我从商店回来,如果仍然没有回答,我会找到解决办法的

标签: python debugging types pycharm conditional-statements


【解决方案1】:

您可以为标准 json 序列化器无法识别的对象创建序列化器:

def my_json_serializer(obj):
    if isinstance(obj, int64):
        return int(obj)    # or whatever other conversion you'd prefer
    raise TypeError ("Type %s not serializable" % type(obj))

然后像这样使用它:

json.dumps( vars(my_object), default=my_json_serializer)

【讨论】:

  • 谢谢 - 这是一个非常优雅的解决方案。事实上,这确实指向了我怀疑的PrintableEntry 对象(请参阅有关问题的 cmets)。由于PrintableEntry 实际上是可序列化的,我应该能够通过添加elif type(obj) == PrintableEntry': return vars(obj) 来解决这个问题。
  • @levraininjaneer 当然,用额外的elif 语句把自己搞垮 =)
  • 啊,通过去掉 int64 子句,我可以找到该值隐藏的位置!谢谢!
【解决方案2】:

两者

my_object.__class__.__name__ == "int64"

type(my_object) == int64 

是检查类型的有效方法。

正如问题编辑中所述,我误解了我的问题。

【讨论】:

  • 如果有人有兴趣解释 json.dumps 的实际工作原理以及为什么 type(o) == int64 从未真正触发过,我将不胜感激。
猜你喜欢
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
相关资源
最近更新 更多