私は次のようなクラスを持っています:
_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
# in python 3:
# class MyClass(metaclass=FooType):
# pass
print MyClass.Foo
print MyClass.Bar
print str(MyClass)
_
印刷:
_foo!
bar!
custom str for MyClass
_
いいえ、オブジェクトは、その属性の1つを文字列化するリクエストを傍受することはできません。属性に対して返されるオブジェクトは、独自の__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
これにより、メタクラスの使用が回避され、いくつかのユースケースが処理されます。