如何通过类本身访问类属性名称以提高 Python 中的可读性和类型提示?

问题描述 投票:0回答:1

假设你有以下课程:

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]

我会受益

  1. 当我在
    MyModel
  2. 上重命名字段时,从我的 IDE 更新字段数组
  3. 在我编写或更新字段数组时,从我的 IDE 显示
    MyModel
    上的所有可用字段。

同样的问题也适用于 Django ORM 的过滤。

结论

请告诉我现在如何做到这一点,或者如何将此功能添加到 Python 语言中 :) 非常感谢!

python django python-class
1个回答
0
投票

您可以使用

.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']

© www.soinside.com 2019 - 2024. All rights reserved.