Python: access class property from string
x = getattr(self, source)
will work just perfectly if source
names ANY attribute of self, including the other_data
in your example.
How to access object attribute given string corresponding to name of that attribute
There are built-in functions called getattr
and setattr
getattr(object, attrname)
setattr(object, attrname, value)
In this case
x = getattr(t, 'attr1')
setattr(t, 'attr1', 21)
Set and Get @property method in Python by string variable
Calling getattr(model_class, model_attribute)
will return the property object that model_attribute
refers to. I'm assuming you already know this and are trying to access the value of the property object.
class A(object):
def __init__(self):
self._myprop = "Hello"
@property
def myprop(self):
return self._myprop
@myprop.setter
def myprop(self, v):
self._myprop = v
prop = getattr(A, "myprop")
print prop
# <property object at 0x7fe1b595a2b8>
Now that we have obtained the property object from the class we want to access its value. Properties have three methods fget
, fset
, and fdel
that provide access to the getter
, settter
, and deleter
methods defined for that property.
Since myprop
is an instance method, we'll have to create an instance so we can call it.
print prop.fget
# <function myprop at 0x7fe1b595d5f0>
print prop.fset
# <function myprop at 0x7fe1b595d668>
print prop.fdel # We never defined a deleter method
# None
a = A()
print prop.fget(a)
# Hello
How to access class property in decorator in Python?
One workaround would be to use a string containing the attribute name in the decorator, and getattr
in the test function:
@parameterized.expand([
("testuser1", "user1", "Bar"),
("testuser2", "user2", "Foo")
])
def test_param(self, name, input, expected):
assert_equal(getattr(self, input), expected)
With this approach, test_param
assumes that the value of its input
argument is the attribute name whose value should be checked against expected
.
Why does getting a class property from an instance raise an AttributeError?
That is due to the way attribute lookup works. Upon trying to retrieve an
attribute in an instance, Python does:
call the instance's class
__getattribute__
(not the metaclass__getattribute__
), which in turn will:Check the instance's class, and its superclasses following the method resolution order, for the attribute. It does not proceed to the class of the class (the metaclass) - it follows the inheritance chain..
- if the attribute is found in the class and it has a
__get__
method, making it a descriptor: the__get__
method is called with the instance and its class as parameters - the returned value is used as the attribute value- note: for classes using
__slots__
, each instance attribute is recorded in a special descriptor - which exists in the class itself and has a__get__
method, so instance attributes for slotted classes are retrieved at this step
- note: for classes using
- if there is no
__get__
method, it just skips the search at the class.
- if the attribute is found in the class and it has a
check the instance itself: the attribute should exist as an entry in the instances
__dict__
attribute. If so, the corresponding value is returned. (__dict__
is an special attribute which is accessed directly in cPython, but would otherwise follow the descriptor rule for slotted attributes, above)The class (and its inheritance hierarchy) are checked again for the attribute, this time, regardless of it having a
__get__
method. If found, that is used. This attribute check in the class is performed directly in the class and its superclasses__dict__
, not by calling their own__getattribute__
in a recursive fashion. (*)
The class (or superclasses)
__getattr__
method is called, if it exists, with the attribute name. It may return a value, or raise AttributeError(__getattr__
is a different thing from the low level__getattribute__
, and easier to customize)AttributeError is raised.
(*) This is the step that answers your question: the metaclass is not searched for an attribute in the instance. In your code above, if you try to use A.cls_prop
as a property, instead of A().cls_prop
it will work: when retrieving an attribute directly from the class, it takes the role of "instance" in the retrieval algorithm above.
(**) NB. This attribute retrieval algorithm description is fairly complete, but for attribute assignment and deletion, instead of retrieval, there are some differences for a descriptor, based on whether it features a __set__
(or __del__
) method, making it a "data descriptor" or not: non-data descriptors (such as regular methods, defined in the instance's class body), are assigned directly on the instance's dict, therefore overriding and "switching off" a method just for that instance. Data descriptors will have their __set__
method called.
how to make properties defined in the metaclass work for instances:
As you can see, attribute access is very customizable, and if you want to define "class properties" in a metaclass that will work from the instance, it is easy to customize your code so that it works. One way is to add to your baseclass (not the metaclass), a __getattr__
that will lookup custom descriptors on the metaclass and call them:
class Base(metaclass=Meta):
def __getattr__(self, name):
metacls = type(cls:=type(self))
if hasattr(metacls, name):
metaattr = getattr(metacls, name)
if isinstance(metaattr, property): # customize this check as you want. It is better not to call it for anything that has a `__get__`, as it would retrieve metaclass specific stuff, such as its __init__ and __call__ methods, if those were not defined in the class.
attr = metaattr.__get__(cls, metacls)
return attr
return super().__getattr__(name)
and:
In [44]: class A(Base):
...: pass
...:
In [45]: a = A()
In [46]: a.cls_prop
Out[46]: True
Check the value of all properties ('@property') on a class
You could use getattr
with the property names in the props
tuple.
valid = [p for p, _ in props if getattr(self, p) is not None]
Remember that accessing a property may execute arbitrary code, so the getting of the value itself might set the value to None
or not None
.
how to access the class variable by string in Python?
To get the variable, you can do:
getattr(test, a_string)
Access a class attribute using django in Python
Attributes of the instance is stored as a dictionary field called __dict__
. However a proper way of getting a field dynamically is by using a getattr
method. Here is an example:
>>> t = Test()
>>> t.b = 2
>>> getattr(t, 'b')
2
>>> getattr(t, 'c', 'default_value')
'default_value'
Call a class attribute which is a string type
Use getattr
getattr
will do exactly what you're asking.
class A:
def __init__(self,a,b):
self.result = ''
self.a = a
self.b = b
self.add()
def add(self):
self.result = self.a+self.b
return
x = 'result' # I will get from other source
obj = A(1,2)
obj.add() #this was missing before thus obj.result would've been 0
print getattr(obj, x) # Here x = result and the result is the actual class attribute
Related Topics
How to Get List of Methods in a Python Class
How to Run an External Command Asynchronously from Python
Python Multiprocessing Linux Windows Difference
How to Search Directories and Find Files That Match Regex
How to Directly Send a Python Output to Clipboard
How to Make a Cross-Module Variable
Sort List of Lists Ascending and Then Descending
Scraping: Ssl: Certificate_Verify_Failed Error for Http://En.Wikipedia.Org
Typeerror: Unhashable Type: 'Dict'
How to Find Length of Digits in an Integer
Pip Install Access Denied on Windows
Differences Between 'Input' and 'Raw_Input'
What's a Correct and Good Way to Implement _Hash_()
Concatenate Rows of Two Dataframes in Pandas
Reshape Wide to Long in Pandas