3.6 之前的 Python 版本中没有 __set_name__ 的解决方法

Nag*_*aga 6 python python-2.7

在Python 3.6中,我可以使用__set_name__钩子来获取描述符的类属性名称。我怎样才能在 python 2.x 中实现这一点?

这是在 Python 3.6 中运行良好的代码:

class IntField:
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, int):
            raise ValueError('expecting integer')
        instance.__dict__[self.name] = value

    def __set_name__(self, owner, name):
        self.name = name

class Example:
    a = IntField()
Run Code Online (Sandbox Code Playgroud)

gec*_*kos 6

您可能正在寻找元类,使用它您可以在类创建时处理类属性。

class FooDescriptor(object):
    def __get__(self, obj, objtype):
        print('calling getter')

class FooMeta(type):
    def __init__(cls, name, bases, attrs):
        for k, v in attrs.iteritems():
            if issubclass(type(v), FooDescriptor):
                print('FooMeta.__init__, attribute name is "{}"'.format(k))

class Foo(object):
    __metaclass__ = FooMeta
    foo = FooDescriptor()


f = Foo()
f.foo
Run Code Online (Sandbox Code Playgroud)

输出:

FooMeta.__init__, attribute name is "foo"
calling getter
Run Code Online (Sandbox Code Playgroud)

如果您需要在创建类之前更改该类,则需要覆盖__new__而不是__init__在元类处。有关此主题的更多信息,请参阅此答案:Is there any Reason to select __new__ over __init__ when Define a metaclass?