__getattr__表示python中的static/class变量

Tux*_*ude 58 python class-method getattr

我有一个类:

class MyClass:
     Foo = 1
     Bar = 2
Run Code Online (Sandbox Code Playgroud)

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

另外,我需要__str__在调用时str(MyClass.Foo)调用自定义方法.Python提供这样的选项吗?

Mat*_*son 66

__getattr__()并且__str__()对于一个对象可以在它的类中找到,所以如果你想为一个类自定义那些东西,你需要class-of-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)
Run Code Online (Sandbox Code Playgroud)

打印:

foo!
bar!
custom str for MyClass
Run Code Online (Sandbox Code Playgroud)

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


shx*_*hx2 15

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

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

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

使用它像:

class MyClass(object):

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

     @classproperty
     def Bar(cls):
        do_something_else()
        return 2
Run Code Online (Sandbox Code Playgroud)

  • 这只有在您事先知道您的房产名称时才会有所帮助。如果您从文件中读取它们并需要动态反应,这将不起作用。 (2认同)

Ign*_*ams 10

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

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

class MyClass(object):
  __metaclass__ = MyMetaclass

print MyClass.Foo
Run Code Online (Sandbox Code Playgroud)

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

  • 不能等待....经过一些谷歌搜索和测试:示例是针对Python 2.x. 在Python 3.x中,您需要:class MyClass(metaclass = MyMetaclass):pass (4认同)
  • @Cyber​​ED:http://docs.python.org/py3k/reference/datamodel.html#metaclasses:“读取类定义时,如果在类定义中的基类之后传递可调用的“metaclass”关键字参数,则将调用给定的可调用函数而不是`type()`。” (2认同)

Jon*_*fer 7

惊讶没有人指出这一点:

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

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

class MyClass(metaclass=FooType):
    pass
Run Code Online (Sandbox Code Playgroud)

作品:

>>> MyClass.Foo
'foo!'
>>> MyClass.Bar
'bar!'
Run Code Online (Sandbox Code Playgroud)

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

class MyClass(object):
    __metaclass__ = FooType
Run Code Online (Sandbox Code Playgroud)

)

其他答案所说的内容str适用于此解决方案:必须在实际返回的类型上实现.

  • 虽然我通常会尽量不发布"谢谢",但我现在非常需要发帖"谢谢":谢谢! (2认同)