__getattr__ 用于静态/类变量
我有一个这样的类:
class MyClass:
Foo = 1
Bar = 2
每当调用 MyClass.Foo
或 MyClass.Bar
时,我希望在返回值之前能调用一个自定义的方法。Python能做到这一点吗?我知道如果我创建这个类的实例,就可以定义自己的 __getattr__
方法。但我的情况是我想直接使用这个类,而不创建任何实例。
另外,当调用 str(MyClass.Foo)
时,我也需要一个自定义的 __str__
方法被调用。Python有这样的选项吗?
5 个回答
13
首先,你需要创建一个元类,并在这个元类上定义 __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
返回一个合适的类型。
23
(我知道这个问题比较老,但其他答案都用到了一个元类...)
你可以使用下面这个简单的 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
100
__getattr__()
和 __str__()
是对象的特殊方法,它们是在对象的类里面定义的。所以,如果你想要为一个类自定义这些方法,你需要用到一个叫做元类的东西。
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):
pass
# # in python 2:
# class MyClass:
# __metaclass__ = FooType
print(MyClass.Foo)
print(MyClass.Bar)
print(str(MyClass))
打印输出:
foo!
bar!
custom str for MyClass
而且,不,对象不能拦截对其某个属性进行字符串化的请求。返回的属性对象必须自己定义 __str__()
的行为。
更新 2023-02-20,适用于 Python 3.x 的默认实现(Python 2 的内容作为注释)。