If the goal is to create a "property" that behaves like such but doesn't receive "self" as a parameter, the straightforward way to do so would be a simple descriptor. class StaticProperty: def __init__(self, fget=None, fset=None, fdel=None): self.fget = fget self.fset = fset self.fdel = fdel def setter(self, fset): self.fset = fset return self def deleter(self, fdel): self.fdel = fdel return self def __get__(self, instance, owner=None): return self.fget() def __set__(self, instance, value): return self.fset(value) def __delete__(self, instance): return self.fdel() Example: class A: @StaticProperty def number(): return 10 @number.setter def number(value): if value != 10: raise ValueError("Invalid assignment") @number.deleter def number(): raise AttributeError("Can't remove it!") For reading it, both from class and instance would work (A.number == a.number). However it behaves like a common property for attribute setting/deleting in the sense that an assignment to the class (e.g. A.number = 11) would replace it and a removal (del A.number) would indeed delete it from the class namespace. To avoid this, the change must happen in the metaclass, so it's no longer that simple. Is there an use case for this scenario, where an attribute assignment (and/or an attribute removal) should do the same thing on both class and instance? On Sat, 18 Dec 2021 at 14:41, Joao S. O. Bueno <jsbueno@python.org.br> wrote:
All that is needed is a descriptor which calls the decorated functiosn without any parameters.
This could serve to use classes as namespaces for "live" globals - if one will do some sort of reactive programing, it might even find some use.
A descriptor with a for that would be something like:
class staticproperty: def __init__(self, func, setter=None): self.func = func self.setter = setter def __get__(self, instance, owner): return self.func
# setter code (won't work statically) def __set__(self, instance, value): return self.setter(value) def setter(self, func): return type(self)(self.func, func)
I wrote the "setter" code above, but actually it won't work statically - for the descriptor protocol to call __set__ it must be operating with an instance of the class. It could still work involving metaclasses - but if you want the setter only, the above snippet should work.
Should it be on the stdlib? I don't think so - its usage would be too specific, and there are differing interpretations to what it should actually do.
On Sat, 18 Dec 2021 at 14:23, Christopher Barker <pythonchb@gmail.com> wrote:
I'm confused about what a staticproperty would even be.
Usually, properties are a way to provide an interface that "looks like" a simple attribute, but does some computation under the hood. But that computation usually requires instance data to do its thing -- so a static one wouldn't be useful.
In fact, in Python, a staticmethod is not very useful at all anyway, all it is is a function that lives in the class namespace. Making it a property would make it look like a class attribute.
Hmm, I guess one use case would be to make a read only class attribute.
Anyway, the thing is that both staticmethod and property are implimented using descriptors, which I think can only be invoked by instance attribute lookup. That is, the class attribute IS a descriptor instance.
And Chris A says -- there may be a way to get a similar effect with Metaclasses, but we'd have to know what your goal is to advise on how to do that.
Note: you can put a descriptor on class, and the __get__ will be called, to get part of what I think you want:
In [52]: class Ten: ...: def __get__(self, obj, objtype=None): ...: return 10 ...: def __set__(self, obj, value): ...: raise AttributeError("attribute can not be set") ...:
In [53]: class A: ...: y = Ten() ...:
# attribute access does call the descriptor's __get__:
In [54]: A.y Out[54]: 10
But setting the attribute replaces the descriptor, rather than raising an exception:
In [55]: A.y = 12
In [56]: A.y Out[56]: 12
Honestly, I don't quite "get" how all this works, but the usual thing is for Descriptors to be invoked on instance attribute access.
-CHB
On Sat, Dec 18, 2021 at 8:30 AM <me@chenjt.com> wrote:
In the following situations:
class Data(object): @staticmethod @property def imagesTotal(): return 10
print(Data.imagesTotal)
The "print(Data.imagesTotal)" can't print "10", it print "<property object at 0x...>".
It might be a good idea to use "@staticproperty" to solve this problem. "@staticproperty" is a decorators, it mix the @staticmethod and @property. Then the static property has getter and setter. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/DEC3AA... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD (Chris)
Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/7WACW2... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/BHHMB7... Code of Conduct: http://python.org/psf/codeofconduct/
-- Danilo J. S. Bellini