假设你有以下课程:
class MyClass:
attribute1: str
attribute2: int
class MySecondClass:
another_attribute1: str
another_attribute2: int
我想通过
'attribute1'
类访问字符串MyClass
。例如MyClass.attribute1.fieldname
,但我找不到这样的选项。如果这样的事情是可能的,你能告诉我吗?我将在下面解释两个可能的用例:
用例 1
假设我想创建一个方法,用
MyClass
的实例更新 MySecondClass
的实例。它应该返回一个布尔值,指示 MyClass
的实例是否已更新。我想将所有要映射的字段放入字典中,以便循环遍历它们。例如
my_class_instance: MyClass
my_second_class_instance: MySecondClass
field_map = {
'attribute1': 'another_attribute1',
'attribute2': 'another_attribute2'
}
updated = False
for field1, field2 in field_map.items():
current_value = getattr(my_class_instance, field1)
new_value = getattr(my_second_class_instance, field2)
if current_value != new_value:
setattr(my_class_instance, field, new_value)
updated = True
return updated
我对这个解决方案的主要问题是,当我重构这段代码时,它没有利用类型提示或我的 IDE 的强大功能。如果我在
attribute1
类上将 attribute_one
重命名为 MyClass
,代码将会中断,因为 field_map
不会自动更新。使用字典可以更容易地引入错误,并使更新此代码变得更加乏味,因为您必须复制并粘贴准确的属性名称,而不是依赖于您的好朋友 IDE。你当然可以通过重写逻辑来解决这个问题:
updated = False
if my_class_instance.attribute1 != my_second_class_instance.another_attribute1:
my_class_instance.attribute1 = my_second_class_instance.another_attribute1
updated = True
if my_class_instance.attribute2 != my_second_class_instance.another_attribute2:
my_class_instance.attribute2 = my_second_class_instance.another_attribute2
updated = True
return updated
但是当有很多字段要比较时,您可以很容易地看到这将变得非常丑陋。
用例 2
我在使用 Django 和 Django Rest Framework 时遇到的一个大问题是到处都使用纯字符串。如果你有这样的模型:
class MyModel(models.Model):
field1 = models.FloatField()
field2 = models.IntegerField()
你的序列化器看起来像这样:
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ['field1', 'field2']
现在,fields 是一个字符串数组。特别是在开发过程中,我经常会重命名一个字段。如果我将
field1
重命名为 my_client_changed_the_requirements
,序列化程序将中断,因为 fields
数组未更新。如果我能像这样构建fields
:
fields = [MyModel.field1.fieldname, MyModel.field2.fieldname]
我会受益
MyModel
MyModel
上的所有可用字段。同样的问题也适用于 Django ORM 的过滤。
结论
请告诉我现在如何做到这一点,或者如何将此功能添加到 Python 语言中 :) 非常感谢!
您可以使用
.field.name
将字段名称作为字符串获取,如下所示:MyClass.attribute1.field.name
。这将输出"attribute1"
.
但我找不到这样的选项。如果这样的事情是可能的,你能告诉我吗?
dir()
函数来了解任何对象的可能方法/属性。像这样:
>> dir(MyClass.attribute1)
['__class__',
'__delattr__',
'__dict__',
'__eq__',
..
'__str__',
'__subclasshook__',
'__weakref__',
'_check_parent_chain',
'field'] # Here's the `field` attribute
>> dir(MyClass.attribute1.field)
['__class__',
'__copy__',
'__deepcopy__',
'__delattr__',
'__dict__',
..
'many_to_one',
'max_length',
'merge_dicts',
'model',
'name', # Here's the `name` attribute
'verbose_name']