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/DEC3AA2NN5KTI5LQ6M7FIRLPDYLNSP7G/
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/7WACW25ZZELEMVWE6CAX7DICPIJUXGYC/
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/BHHMB75QGOVCA5SU6QU57EDQHY4RN2TQ/
Code of Conduct: http://python.org/psf/codeofconduct/


--
Danilo J. S. Bellini