我有一个类,如下:
class MyClass:
Foo = 1
Bar = 2
每当调用
MyClass.Foo
或MyClass.Bar
时,我需要在返回值之前调用自定义方法。在Python中是否可能?我知道如果我创建类的实例并且可以定义自己的__getattr__
方法,那么这是可能的。但我的场景涉及在不创建任何实例的情况下使用此类。另外,当调用
str(MyClass.Foo)
时,我需要调用自定义__str__
方法。Python是否提供了这样的选项?我有一个类,如下:
class MyClass:
Foo = 1
Bar = 2
MyClass.Foo
或MyClass.Bar
时,我需要在返回值之前调用自定义方法。在Python中是否可能?我知道如果我创建类的实例并且可以定义自己的__getattr__
方法,那么这是可能的。但我的场景涉及在不创建任何实例的情况下使用此类。str(MyClass.Foo)
时,我需要调用自定义__str__
方法。Python是否提供了这样的选项?__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以注释形式提供)。
我知道这是一个旧问题,但由于所有其他答案都使用元类,因此...
您可以使用以下简单的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
setattr(MyClass, prop_name, classproperty(..., ...))
。 - ntjess首先,你需要创建一个元类,然后在其中定义__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
返回一个适当的类型。
metaclass
关键字参数,则将调用给定的可调用对象,而不是type()
。” - Ignacio Vazquez-Abrams我很惊讶没有人指出这一点:
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
AttributeError
,请查看其他答案,其中包含Python3的语法(此示例似乎是Python2)。 - Chrisprint
语句之外,唯一需要更改的是元类的指定方式(如现在所述的评论中)。 - martineau