Python 自定义 class 迭代器不适用于默认值

Python custom class iterator not working for default values

大家好,我有一个自定义 class MyClass。我想迭代它的默认值。我认为我的问题最好用一个例子来说明:

class MyClass:
    def __iter__(self):
        for each in self.__dict__.values():
            yield each

    first_var: str = "asdf"
    second_var: str = "tasdt"


my_class = MyClass()

for var in my_class:  # this does not work, how can i get this to work?
    print(var)

my_class.first_var = "hello" # setting the variables makes it work
my_class.second_var = "world"

for var in my_class:  # now it works
    print(var)

正如您从示例中看到的那样,第一个 for 循环不打印 class MyClass 的默认值。我怎样才能做到这一点?

编辑:根据我尝试过的 C Hecht 的评论

def __iter__(self):
    for attribute in self.__dict__.keys():
        if attribute[:2] != '__':
            value = getattr(self, attribute)
            if not callable(value):
                print(attribute, '=', value)
                yield value

仍然没有得到那些 class 属性

以上不起作用的原因是 self.__dict__ 持有 实例值 。这些通常是通过设置属性添加到 class 的值:

my_class = MyClass()

my_class.__dict__ # {}

my_class.x = 1    # {'x': 1} 

如果你想访问 class 属性 first_varsecond_var 那么你应该查看方法 vars

例如:


for k, v in vars(MyClass.items()): 
    print(x, y)
# __module__ __main__
# __iter__ <function MyClass.__iter__ at 0x10e22fca0>
# first_val first
# second_var second
# __dict__ <attribute '__dict__' of 'MyClass' objects>
# __weakref__ <attribute '__weakref__' of 'MyClass' objects>
# __doc__ None

如果你只想得到你想要的值,你需要做类似的事情:

def __iter__(self):
    for k, v in vars(type(self)).items(): # need type(self) to refer to the class
        if not k.startswith('_'): 
            yield v

问题是因为您迭代的是 class Myclass 的“实例”属性,而不是 class 本身的属性。那些 first_varsecond_var 是 class 属性:

如果你想获得全部class个属性:

class MyClass:
    def __iter__(self):
        for each in self.__class__.__dict__.values():
            yield each

    first_var: str = "asdf"
    second_var: str = "tasdt"


my_class = MyClass()

for var in my_class:
    print(var)

当然,您可能希望通过是否可调用来过滤它,从 dunder 或 ...

开始

@dataclass修饰Pythonclass以实现class实例字段的默认初始化。 It's available 自 Python 3.7 以来,它隐式地将 __init__ 构造函数添加到 class 中,后者使用您指定的默认值初始化 class 实例。

from dataclasses import dataclass

@dataclass
class MyClass:
    def __iter__(self):
        for each in self.__dict__.values():
            yield each

    first_var: str = "asdf"
    second_var: str = "tasdt"


my_class = MyClass()

for var in my_class:
    print(var)

打印

asdf
tasdt