admin管理员组文章数量:1242847
My code dynamically generates properties and the classes to contain them. The code creates immutably-typed properties such that assignments to them are automatically converted to the correct type, rather than be rejected.
The problem is that, for property c.p the getter (t=c.p
) and setter (c.p=t
) are not being invoked. Code can explicitly invoke the getter with t=w.p.__get__(0)
. Code can explicitly invoke the setter with c.p.__set__(3,0)
. However, that ruins the convenience of having properties in the first place.
Symptoms:
for property p in class c:
t=c.p
does not invoke the getter. Instead the assignment causes t to then refer to the property object itself, rather than the property's value.
t=c.p.__get__()
fails with TypeError: expected at least 1 argument, got 0
t=c.p.__get__(None)
fails with TypeError: get(None, None) is invalid
t=c.p.__get__(0)
invokes the getter. t gets the value returned by the getter. The value of the parameter does not matter, as long as it is not None.
c.p=3
does not invoke the setter. Instead, c.p is now an integer with value 3.
After reconstructing the property:
c.p.__set__(3)
fails with TypeError: expected 2 arguments, got 1
c.p.__set__(3,0)
fails with TypeError: fImmutablyTypedPropertiesContainer..cImmutablyTypedPropertiesContainer.addProperty..psetter() takes from 0 to 1 positional arguments but 2 were given
Altering the setter's signature to accept a optional second parameter then allows c.p.__set__(3,0)
or even c.p.__set__(3,None)
to work.
c.p.__set__(3,0)
# now works
What must be done to get the property's typical usage to invoke the getter and setter as intended?
code:
#!/bin/python3.13
# immutably typed properties (the type survives setting a new value)
import numpy as np
def fImmutablyTypedPropertiesContainer():
# Purpose: Create a Class to be a container to which staticly typed properties can be added, then can get and set.
# Each property's type is immutable, although its value may change. An np.longdouble stays an np.longdouble.
# Each call creates and returns a new class, NOT an instance. No instances are created.
# That way multiple invocations of this function each get their own container and namespace.
# The static typing survives a set to a new value, even if conversion & coercion at assignment time is required.
# Different properties within the container need not all be of the same type.
#
# Usage:
# bucket= fImmutablyTypedPropertiesContainer() # create a container
# bucket.addProperty('i',75.6,ptype=np.int64) # add a property i with value stored in _i[0] set to 75
# bucket.addProperty('x',144,ptype=np.longdouble) # add a property x with value stored in _x[0] set to 144.0
# bucket.i # get i's value
# bucket.x = 44 # set x's value to 44.0
#
# import numpy as np # assume already imported
# create the class
class cImmutablyTypedPropertiesContainer(object):
pass # no instances
@classmethod
def addProperty(cls,name,value=np.longdouble(2.71828182845),ptype=np.longdouble) : #cls is the class, not an instance.
# name is a string, such as "i"
setattr(cls, "_"+name, np.ndarray((1,),dtype=ptype) ) # create an array containing a single item as an attribute called _name
# elements of a numpy array have a static type, with conversion & coercion at assignment time
getattr(cls, "_"+name)[0]=value # this SETs the initial value of the only element of the _name array, including automatic type conversion.
print("adding property named: ", name ," to class: ", cls," at", id(cls), ". with parm value:", value, " in ", "_"+name, "with value ",getattr(cls, "_"+name)," \n" )
#MUST NOT BE @classmethod. Causes TypeError: 'classmethod' object is not callable
def pgetter(a1):#*args,**kwargs): # arguments are unused
t=pgetter.fromwhattoget[0] # set externally
print("invoked the getter for name= ",name, pgetter.fromwhattoget, "; value= ",t, ". a1=",a1)
# elements of a numpy array have a static type, with conversion & coercion at assignment time
return t
pgetter.fromwhattoget=getattr(cls, "_"+name)
#MUST NOT BE @classmethod. Causes TypeError: 'classmethod' object is not callable
def psetter(newvalue=3.14159, dummyparm=0): #must allow for two parameters
print("invoked a setter for name ",name, psetter.intowhattoset, " = ",newvalue)
# elements of a numpy array have a static type, with conversion & coercion at assignment time
psetter.intowhattoset[0]=newvalue # this SETs a value of the first element of the _name array, including automatic type conversion.
return psetter.intowhattoset[0] # getattr(cls, "_"+name)[0] # also returns the value, but the __get__ function does not pass it back.
psetter.intowhattoset=getattr(cls, "_"+name)
print("fromwhat to get and into what toset = ",pgetter.fromwhattoget, psetter.intowhattoset)
setattr(cls,name, property( fget=pgetter, fset=psetter) )
return
return cImmutablyTypedPropertiesContainer # return the class itself, not an instance
v=fImmutablyTypedPropertiesContainer() # v is a unique class itself, rather than an instance.
v.addProperty('i',1024,ptype=np.int64)
w=fImmutablyTypedPropertiesContainer() # w is a unique class itself, rather than an instance.
w.addProperty('i',75.6,ptype=np.int64)
print("added property named: w.i", w.i, w.i.__get__(0), type(w.i)," to class: ",w," with parm value: 75.6, ", "but actual value: ", w.i )
print("\n getting:")
t=w.i
tg=w.i.__get__
tv=w.i.__get__(10) # must have a parameter, even though the getter does not use it. Cannot be None.
print("t=w.i= ",t,", getter:", tg, ", value:", tv)
print("\n setting:")
ts=w.i.__set__
w.i.__set__(314,None) #must have two parameters, even though the setter does not use the second.
tv=w.i.__get__(w.i)
print("t=w.i= ",t,", setter:", ts,", value:", tv)
tvr=w.i.__set__(342,0) #must have two parameters, even though the setter does not use the second.
tv=w.i.__get__(w.i)
print("t=w.i= ",t,", setter:", ts,", value:", tv, tvr) # tvr is None. __set__ does not return a value.
t=w.i
print("t=w.i= ",t,", w.i=",w.i,", with type=",type(w.i))
print("\n")
print("w.i= ",w.i.__get__(0), type(w.i), w.i,w, type(w), id(w))
print("v.i= ",v.i.__get__(0), type(v.i), v.i,v, type(v), id(v))
w.i=3
t=w.i
print("t=w.i= ",t,", w.i=",w.i,", with type=",type(w.i))
print("\n")
print("w.i= ",w.i.__get__(0), type(w.i), w.i,w, type(w), id(w))
quit()
references:
- How to add property to a class dynamically? # see the top answer
- .py?rlkey=q8rqcpufdf4lva2y0ahmih798&e=1&dl=0
- .html#properti
- /
- Python: Dynamically add properties to class instance, properties return function value with inputs
- Dynamically adding @property in python
- .html
- /
- /
- Setter ignored when property is assigned to variable (Python 3.4)
- @property setter not called in python 3
- Python property being ignored, acting like an attribute
- creating class properties dynamically
- pythonic way to declare multiple class instance properties as numbers?
- Dynamic python properties
- Is there a way to type hint a class property created without the property decorator?
My code dynamically generates properties and the classes to contain them. The code creates immutably-typed properties such that assignments to them are automatically converted to the correct type, rather than be rejected.
The problem is that, for property c.p the getter (t=c.p
) and setter (c.p=t
) are not being invoked. Code can explicitly invoke the getter with t=w.p.__get__(0)
. Code can explicitly invoke the setter with c.p.__set__(3,0)
. However, that ruins the convenience of having properties in the first place.
Symptoms:
for property p in class c:
t=c.p
does not invoke the getter. Instead the assignment causes t to then refer to the property object itself, rather than the property's value.
t=c.p.__get__()
fails with TypeError: expected at least 1 argument, got 0
t=c.p.__get__(None)
fails with TypeError: get(None, None) is invalid
t=c.p.__get__(0)
invokes the getter. t gets the value returned by the getter. The value of the parameter does not matter, as long as it is not None.
c.p=3
does not invoke the setter. Instead, c.p is now an integer with value 3.
After reconstructing the property:
c.p.__set__(3)
fails with TypeError: expected 2 arguments, got 1
c.p.__set__(3,0)
fails with TypeError: fImmutablyTypedPropertiesContainer..cImmutablyTypedPropertiesContainer.addProperty..psetter() takes from 0 to 1 positional arguments but 2 were given
Altering the setter's signature to accept a optional second parameter then allows c.p.__set__(3,0)
or even c.p.__set__(3,None)
to work.
c.p.__set__(3,0)
# now works
What must be done to get the property's typical usage to invoke the getter and setter as intended?
code:
#!/bin/python3.13
# immutably typed properties (the type survives setting a new value)
import numpy as np
def fImmutablyTypedPropertiesContainer():
# Purpose: Create a Class to be a container to which staticly typed properties can be added, then can get and set.
# Each property's type is immutable, although its value may change. An np.longdouble stays an np.longdouble.
# Each call creates and returns a new class, NOT an instance. No instances are created.
# That way multiple invocations of this function each get their own container and namespace.
# The static typing survives a set to a new value, even if conversion & coercion at assignment time is required.
# Different properties within the container need not all be of the same type.
#
# Usage:
# bucket= fImmutablyTypedPropertiesContainer() # create a container
# bucket.addProperty('i',75.6,ptype=np.int64) # add a property i with value stored in _i[0] set to 75
# bucket.addProperty('x',144,ptype=np.longdouble) # add a property x with value stored in _x[0] set to 144.0
# bucket.i # get i's value
# bucket.x = 44 # set x's value to 44.0
#
# import numpy as np # assume already imported
# create the class
class cImmutablyTypedPropertiesContainer(object):
pass # no instances
@classmethod
def addProperty(cls,name,value=np.longdouble(2.71828182845),ptype=np.longdouble) : #cls is the class, not an instance.
# name is a string, such as "i"
setattr(cls, "_"+name, np.ndarray((1,),dtype=ptype) ) # create an array containing a single item as an attribute called _name
# elements of a numpy array have a static type, with conversion & coercion at assignment time
getattr(cls, "_"+name)[0]=value # this SETs the initial value of the only element of the _name array, including automatic type conversion.
print("adding property named: ", name ," to class: ", cls," at", id(cls), ". with parm value:", value, " in ", "_"+name, "with value ",getattr(cls, "_"+name)," \n" )
#MUST NOT BE @classmethod. Causes TypeError: 'classmethod' object is not callable
def pgetter(a1):#*args,**kwargs): # arguments are unused
t=pgetter.fromwhattoget[0] # set externally
print("invoked the getter for name= ",name, pgetter.fromwhattoget, "; value= ",t, ". a1=",a1)
# elements of a numpy array have a static type, with conversion & coercion at assignment time
return t
pgetter.fromwhattoget=getattr(cls, "_"+name)
#MUST NOT BE @classmethod. Causes TypeError: 'classmethod' object is not callable
def psetter(newvalue=3.14159, dummyparm=0): #must allow for two parameters
print("invoked a setter for name ",name, psetter.intowhattoset, " = ",newvalue)
# elements of a numpy array have a static type, with conversion & coercion at assignment time
psetter.intowhattoset[0]=newvalue # this SETs a value of the first element of the _name array, including automatic type conversion.
return psetter.intowhattoset[0] # getattr(cls, "_"+name)[0] # also returns the value, but the __get__ function does not pass it back.
psetter.intowhattoset=getattr(cls, "_"+name)
print("fromwhat to get and into what toset = ",pgetter.fromwhattoget, psetter.intowhattoset)
setattr(cls,name, property( fget=pgetter, fset=psetter) )
return
return cImmutablyTypedPropertiesContainer # return the class itself, not an instance
v=fImmutablyTypedPropertiesContainer() # v is a unique class itself, rather than an instance.
v.addProperty('i',1024,ptype=np.int64)
w=fImmutablyTypedPropertiesContainer() # w is a unique class itself, rather than an instance.
w.addProperty('i',75.6,ptype=np.int64)
print("added property named: w.i", w.i, w.i.__get__(0), type(w.i)," to class: ",w," with parm value: 75.6, ", "but actual value: ", w.i )
print("\n getting:")
t=w.i
tg=w.i.__get__
tv=w.i.__get__(10) # must have a parameter, even though the getter does not use it. Cannot be None.
print("t=w.i= ",t,", getter:", tg, ", value:", tv)
print("\n setting:")
ts=w.i.__set__
w.i.__set__(314,None) #must have two parameters, even though the setter does not use the second.
tv=w.i.__get__(w.i)
print("t=w.i= ",t,", setter:", ts,", value:", tv)
tvr=w.i.__set__(342,0) #must have two parameters, even though the setter does not use the second.
tv=w.i.__get__(w.i)
print("t=w.i= ",t,", setter:", ts,", value:", tv, tvr) # tvr is None. __set__ does not return a value.
t=w.i
print("t=w.i= ",t,", w.i=",w.i,", with type=",type(w.i))
print("\n")
print("w.i= ",w.i.__get__(0), type(w.i), w.i,w, type(w), id(w))
print("v.i= ",v.i.__get__(0), type(v.i), v.i,v, type(v), id(v))
w.i=3
t=w.i
print("t=w.i= ",t,", w.i=",w.i,", with type=",type(w.i))
print("\n")
print("w.i= ",w.i.__get__(0), type(w.i), w.i,w, type(w), id(w))
quit()
references:
- How to add property to a class dynamically? # see the top answer
- https://stackoverflow/users/saves/1496279
- https://www.dropbox/scl/fi/vahot6oi1ddt3epasyyie/dynamic_properties_simple.py?rlkey=q8rqcpufdf4lva2y0ahmih798&e=1&dl=0
- https://www.programiz/python-programming/property
- https://docs.python./2/howto/descriptor.html#properti
- https://realpython/python-property/
- Python: Dynamically add properties to class instance, properties return function value with inputs
- Dynamically adding @property in python
- https://github/Infinidat/munch
- https://docs.python./3/tutorial/classes.html
- https://discuss.python./t/dynamic-generation-of-methods-for-a-class-from-a-list-of-names/14566
- https://discuss.python./t/dynamic-generation-of-methods-for-a-class-from-a-list-of-names/14566/2
- https://www.geeksfeeks./classmethod-in-python/
- https://www.programiz/python-programming/methods/built-in/classmethod
- https://mgarod.medium/dynamically-add-a-method-to-a-class-in-python-c49204b85bd6
- https://tush.ar/post/descriptors/
- Setter ignored when property is assigned to variable (Python 3.4)
- @property setter not called in python 3
- Python property being ignored, acting like an attribute
- creating class properties dynamically
- pythonic way to declare multiple class instance properties as numbers?
- Dynamic python properties
- Is there a way to type hint a class property created without the property decorator?
1 Answer
Reset to default 0The answer is that a property's getter and setter are invoked only from an instance.
The example that demonstrates this is within https://stackoverflow/a/7118013/1496279 .
> print Bar.x > # < property object at 0x04D37270> > print Bar () .x > # 0
The ( ) creates an instance.
本文标签: Dynamically created Python properties not invoking getters and gettersStack Overflow
版权声明:本文标题:Dynamically created Python properties not invoking getters and getters - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1740130413a2229643.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
share
button. "top answer" is meaningless because order is dynamic. – Barmar Commented Feb 17 at 21:21fImmutablyTypedPropertiesContainer
ALWAYS returns the SAME class. Your comment that each returned value is a new, unique class is incorrect. Your variables 'v' and 'w' both refer to the same object, which is a class (not an instance). You never instantiate an instance, so what you are doing here is manipulating values in the dictionarycImmutablyTypedPropertiesContainer.__dict__
. That's why t.c doesn't invoke the getter - the getter is invoked to assigned a value to the__dict__
of an instance. – Paul Cornelius Commented Feb 17 at 23:35fImmutablyTypedPropertiesContainer
does return a class with a different ID. The fundamental problem was that a property's getters and setters are only called when the getting and setting are through an instance.z=classx.propertyy
results inz
referring to a property objectz=instancewofclassx.propertyy
results inz
getting the value returned by the property's getter. – user15972 Commented 2 days ago