如何在 Python 中定义作为 class 实例的 class 字段?
How to define class field in Python that is an instance of a class?
我想在 class 的命名空间中获取特定的 class 实例。在 C# 中,它看起来像这样:
public struct Foo
{
public readonly static Bar = new Foo();
}
我唯一的想法是在 class 定义(monkeypatch)之后立即分配一个实例:
class Foo:
def __init__(self, spam):
self.spam = spam
Foo.bar = Foo(42)
但我想在 class 定义中提供实例,如下所示:
class Foo:
...
bar = Foo(42)
界面是这样的:
from foo import Foo
bar = Foo.bar
定义的最后一行给出语法错误,因为 Foo 尚未定义。除了 monkeypatching class?
有没有办法克服这个限制
要达到 class 级别,您需要 @classmethod
装饰器。
class Foo:
# Class variable
Bar = None
def __init__(self, value):
self.val = value
Foo.update_Bar(self)
@classmethod
def update_Bar(cls, new_instance):
cls.Bar = new_instance
print(Foo.Bar is None)
foo1 = Foo(10)
print(Foo.Bar.val)
foo2 = Foo(20)
print(Foo.Bar.val)
print(foo1.Bar.val)
你可以把它做成一个外部可调用的方法,比如:-
class Foo:
def __init__(self,data):
self.data = data
def update(self,value):
self.bar = Foo(value)
self.show()
def show(self):
print(self.bar.data,"Updated Successfully")
if __name__ == "__main__":
node = Foo(None)
node.update(10)
node.update(20)
node.update("Hello World")
此代码的输出如下:-
10 Updated Successfully
20 Updated Successfully
Hello World Updated Successfully
您可以通过 :-
直接使用 bar(new instance)
#node.bar.data
print(node.bar.data)
输出将是最后更新的值,即:-
Hello World
请求的功能可以通过自定义描述符对象 (doc) 实现:
class static_property:
def __init__(self, getter):
self.__getter = getter
def __get__(self, obj, objtype):
return self.__getter(objtype)
@staticmethod
def __call__(getter_fn):
return static_property(getter_fn)
class A:
_bar = None
def __init__(self, spam):
self.spam = spam
@static_property
def bar(cls):
if cls._bar is None:
cls._bar = A(10)
return cls._bar
print('A.bar={} A.bar.spam={}'.format(A.bar, A.bar.spam))
a = A(20)
print('a.bar={} a.bar.spam={} a.spam={}'.format(a.bar, a.bar.spam, a.spam))
打印:
A.bar=<__main__.A object at 0x7f0ab5e41eb8> A.bar.spam=10
a.bar=<__main__.A object at 0x7f0ab5e41eb8> a.bar.spam=10 a.spam=20
如果你想为此使用 Metaclasses,那么你可以使用以下内容。确实不知道你为什么要这样,也不知道我介绍的这个方法好不好,但是效果很好。
class Meta(type):
def __new__(cls, name, bases, dct):
print(cls,name, bases, dct)
x = super(Meta, cls).__new__(cls, name, bases, dct)
x.bar = x(46) //create the bar for the Foo
return x
class Foo:
__metaclass__ = Meta
def __init__(self, spam):
self.spam = spam
这样做只是在为 class 创建对象的同时为 Foo
创建一个 bar
命名属性。我想代码是不言自明的
我想在 class 的命名空间中获取特定的 class 实例。在 C# 中,它看起来像这样:
public struct Foo
{
public readonly static Bar = new Foo();
}
我唯一的想法是在 class 定义(monkeypatch)之后立即分配一个实例:
class Foo:
def __init__(self, spam):
self.spam = spam
Foo.bar = Foo(42)
但我想在 class 定义中提供实例,如下所示:
class Foo:
...
bar = Foo(42)
界面是这样的:
from foo import Foo
bar = Foo.bar
定义的最后一行给出语法错误,因为 Foo 尚未定义。除了 monkeypatching class?
有没有办法克服这个限制要达到 class 级别,您需要 @classmethod
装饰器。
class Foo:
# Class variable
Bar = None
def __init__(self, value):
self.val = value
Foo.update_Bar(self)
@classmethod
def update_Bar(cls, new_instance):
cls.Bar = new_instance
print(Foo.Bar is None)
foo1 = Foo(10)
print(Foo.Bar.val)
foo2 = Foo(20)
print(Foo.Bar.val)
print(foo1.Bar.val)
你可以把它做成一个外部可调用的方法,比如:-
class Foo:
def __init__(self,data):
self.data = data
def update(self,value):
self.bar = Foo(value)
self.show()
def show(self):
print(self.bar.data,"Updated Successfully")
if __name__ == "__main__":
node = Foo(None)
node.update(10)
node.update(20)
node.update("Hello World")
此代码的输出如下:-
10 Updated Successfully
20 Updated Successfully
Hello World Updated Successfully
您可以通过 :-
直接使用 bar(new instance)#node.bar.data
print(node.bar.data)
输出将是最后更新的值,即:-
Hello World
请求的功能可以通过自定义描述符对象 (doc) 实现:
class static_property:
def __init__(self, getter):
self.__getter = getter
def __get__(self, obj, objtype):
return self.__getter(objtype)
@staticmethod
def __call__(getter_fn):
return static_property(getter_fn)
class A:
_bar = None
def __init__(self, spam):
self.spam = spam
@static_property
def bar(cls):
if cls._bar is None:
cls._bar = A(10)
return cls._bar
print('A.bar={} A.bar.spam={}'.format(A.bar, A.bar.spam))
a = A(20)
print('a.bar={} a.bar.spam={} a.spam={}'.format(a.bar, a.bar.spam, a.spam))
打印:
A.bar=<__main__.A object at 0x7f0ab5e41eb8> A.bar.spam=10
a.bar=<__main__.A object at 0x7f0ab5e41eb8> a.bar.spam=10 a.spam=20
如果你想为此使用 Metaclasses,那么你可以使用以下内容。确实不知道你为什么要这样,也不知道我介绍的这个方法好不好,但是效果很好。
class Meta(type):
def __new__(cls, name, bases, dct):
print(cls,name, bases, dct)
x = super(Meta, cls).__new__(cls, name, bases, dct)
x.bar = x(46) //create the bar for the Foo
return x
class Foo:
__metaclass__ = Meta
def __init__(self, spam):
self.spam = spam
这样做只是在为 class 创建对象的同时为 Foo
创建一个 bar
命名属性。我想代码是不言自明的