繁体   English   中英

__getattr__ 用于静态/类变量

[英]__getattr__ for static/class variables

我有一个像这样的课程:

class MyClass:
     Foo = 1
     Bar = 2

每当MyClass.FooMyClass.Bar时,我都需要在返回值之前调用自定义方法。 在 Python 中可能吗? 我知道如果我创建一个类的实例并且我可以定义我自己的__getattr__方法是可能的。 但是我的场景涉及使用此类而不创建它的任何实例。

我还需要在调用str(MyClass.Foo)时调用自定义__str__方法。 Python 是否提供这样的选项?

对象的__getattr__()__str__()可以在其类中找到,所以如果你想为一个类定制这些东西,你需要 class-of-a-class。 一个元类。

class FooType(type):
    def _foo_func(cls):
        return 'foo!'

    def _bar_func(cls):
        return 'bar!'

    def __getattr__(cls, key):
        if key == 'Foo':
            return cls._foo_func()
        elif key == 'Bar':
            return cls._bar_func()
        raise AttributeError(key)

    def __str__(cls):
        return 'custom str for %s' % (cls.__name__,)

class MyClass:
    __metaclass__ = FooType

# # in python 3:
# class MyClass(metaclass=FooType):
#     pass


print(MyClass.Foo)
print(MyClass.Bar)
print(str(MyClass))

印刷:

foo!
bar!
custom str for MyClass

不,一个对象不能拦截对其属性之一进行字符串化的请求。 为属性返回的对象必须定义自己的__str__()行为。

(我知道这是一个老问题,但由于所有其他答案都使用元类......)

您可以使用以下简单的classproperty描述符:

class classproperty(object):
    """ @classmethod+@property """
    def __init__(self, f):
        self.f = classmethod(f)
    def __get__(self, *a):
        return self.f.__get__(*a)()

像这样使用它:

class MyClass(object):

     @classproperty
     def Foo(cls):
        do_something()
        return 1

     @classproperty
     def Bar(cls):
        do_something_else()
        return 2

首先,您需要创建一个元类,并在其上定义__getattr__()

class MyMetaclass(type):
  def __getattr__(self, name):
    return '%s result' % name

class MyClass(object):
  __metaclass__ = MyMetaclass

print MyClass.Foo

对于第二个,没有。 调用str(MyClass.Foo)会调用MyClass.Foo.__str__() ,因此您需要为MyClass.Foo返回适当的类型。

很惊讶没有人指出这一点:

class FooType(type):
    @property
    def Foo(cls):
        return "foo!"

    @property
    def Bar(cls):
        return "bar!"

class MyClass(metaclass=FooType):
    pass

作品:

>>> MyClass.Foo
'foo!'
>>> MyClass.Bar
'bar!'

(对于 Python 2.x,将MyClass的定义更改为:

class MyClass(object):
    __metaclass__ = FooType

)

其他答案对str的看法适用于该解决方案:它必须在实际返回的类型上实现。

根据我使用这种模式的情况

class _TheRealClass:
    def __getattr__(self, attr):
       pass

LooksLikeAClass = _TheRealClass()

然后你导入并使用它。

from foo import LooksLikeAClass
LooksLikeAClass.some_attribute

这避免了使用元类,并处理一些用例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM