I want to get a specific class instance in the class's namespace. In C# this would look like this:
public struct Foo
{
public readonly static Bar = new Foo();
}
The only idea I have is to assign an instance right after the class definition (monkeypatch):
class Foo:
def __init__(self, spam):
self.spam = spam
Foo.bar = Foo(42)
But I want to provide instance in class definition, like this:
class Foo:
...
bar = Foo(42)
And interface like this:
from foo import Foo
bar = Foo.bar
The last line in definition gives a syntax error because Foo is not yet defined. Is there a way to overcome this constraint except monkeypatching class?
The requested functionality can be achieved with custom descriptor object (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))
Prints:
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
If you want to use Metaclasses for this then you can use following. I indeed don't know why you want to achieve this, or whether the method I present is good, but nevertheless it works well.
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
What this does is simply create a bar named attribute for the Foo while creating the object for the class. I guess the code is self explanatory
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With