This question already has answers here:
In a Python object, how can I see a list of properties that have been defined with the #property decorator?
(5 answers)
Closed 2 years ago.
In Python, how can I get all properties of a class, i.e. all members created by the #property decorator?
There are at least two questions[1, 2] on stackoverflow which confound the terms property and attribute, falsely taking property as a synonym for attribute, which is misleading in Python context. So, even though the other questions' titles might suggest it, they do not answer my question.
[1]: Print all properties of a Python Class
[2]: Is there a built-in function to print all the current properties and values of an object?
We can get all attributes of a class cls by using cls.__dict__. Since property is a certain class itself, we can check which attributes of cls are an instance of property:
from typing import List
def properties(cls: type) -> List[str]:
return [
key
for key, value in cls.__dict__.items()
if isinstance(value, property)
]
Related
This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 1 year ago.
I am looking for the possibility to add a variable amount of attributes to a class in python using a list.
class X():
def __init__(self,mylist):
for element in list:
self.element = ''
So if I have
tabs = ['food','name','map']
I will get a class with attributes as follows (pseudocode)
myclass = X(['food','name','map'])
print(X.food)
''
I will be able later on to modify X.food from other class.
LATE EDIT: The question: How to access object attribute given string corresponding to name of that attribute is similar but does not use a list to provide names or arguments to the class. Moreover in that particular question setattr is not used in any of the answers. Hence the answers of this question are the ones to follow.
You can use setattr.
class X:
def __init__(self, attrs):
for attr in attrs:
setattr(self, attr, "")
Use setattr:
class X():
def __init__(self,mylist):
for element in mylist:
setattr(self, element, '')
This adds the attributes to the class instance myclass, if you want to add to the class target X instead of self:
setattr(X, element, '')
This question already has answers here:
How do you change the value of one attribute by changing the value of another? (dependent attributes)
(1 answer)
Call Python Method on Class Attribute Change
(2 answers)
Detecting class attribute value change and then changing another class attribute
(1 answer)
Closed 2 years ago.
For example, I have a class:
import datetime
class Obj:
def __init__(self, attribute_1):
self.attribute_1 = attribute_1
self.last_edited = None
I want it to be able to do this:
# Creating object
obj1 = Obj("a")
obj1.attribute_1 = "b" # obj1.last_edited should have changed to datetime.datetime.now()
I'm not sure how to implement the changing of obj1's 'last_edited' attribute if I were to directly change obj1's 'attribute_1' (without any setters).
Thanks in advance.
All Python objects have a builtin method called __setattr__ that is called whenever a field in the class is changed. This method by default updates a value in the class dictionary (stored internally to represent the state of a class instance). You can override this behavior by defining a custom __setattr__ method. For your use case, the function might look like this:
class SomeObject:
def __init__(self, attr):
self.attr = attr
def __setattr__(self, name, value):
super().__setattr__("last_edited", time.time())
super().__setattr__(name, value)
Notice that we need to use a super call to avoid recursion (use the __setattr__ method of the base object class).
This question already has answers here:
How do I check (at runtime) if one class is a subclass of another?
(10 answers)
Closed 3 years ago.
At runtime, I want to check whether a specified child class is derived from a specified parent class.
With an object instance, it's easy:
def is_related(child_instance, parent_type):
return isinstance(child_instance, parent_type)
Is there some way to do this without having (or creating) an instance of the child but, instead, having a reference to the child's type?
Something like...
def is_related(child_type, parent_type):
return is_child_class(child_type, parent_type)
Provide an implementation for is_child_class will answer this question.
(By comparison, types in C# know about their supertypes. I don't know whether this is also true in Python.)
Let's say that ChildClass is a subclass of ParentClass. Then
issubclass(ChildClass, ParentClass)
would return True
Here is a possible solution:
class A:
pass
class B(A):
pass
issubclass(B, A) # True
This is what you need to define the is_child_class method as:
def is_child_class(child_type, parent_type):
return issubclass(child_type, parent_type)
This question already has answers here:
What is the difference between class and instance attributes?
(5 answers)
Closed 5 years ago.
Came across one Python Class and I am finding it hard to understand how and why its working . A simplified example of the class is :
class Test:
def __init__(self):
self.var = 1
otherVar = 2
def myPrinter(self):
print self.__dict__ # Prints {'var': 1}
print self.var
print self.otherVar # Doubt !!
print self.__dict__ # Prints {'var': 1}
ob = Test()
ob.myPrinter()
My doubt is with the self.otherVar call not throwing an error while self.__dict__ does not show reference to otherVar
It's because otherVar is an attribute of the class, while the var you setup in the __init__ is an attribute of the instance.
The otherVar is visible to the instance, because python first tries to get the instance attribute values, if the instance doesn't have it, then it checks its class attributes. If you define a var in both with different values, things may get confusing at first.
Well, do you know that comparison that a class is like a blueprint and the instance is the object built following it, right? So, var is an extra you added while creating the instance.
If you want to see otherVar, do Test.__dict__. It won't show you var, but all the class attributes.
Play a little with it and with time you are going to get used to it. Class attributes may be tricky, but extremely useful.
otherVar is a class member, not instance member, that's why it doesn't show in __dict__.
It appears in self.__class__.__dict__. (this way doesn't work in Python 2.x)
By the way, otherVar member value is shared across all instances and also accessible from type object: Test.otherVar
Example here: https://trinket.io/python3/d245351e58
For a more in depth explanation check here
This question already has answers here:
How to read class attributes in the same order as declared?
(7 answers)
Closed 5 years ago.
Python comes with the handy dir() function that would list the content of a class for you. For example, for this class:
class C:
i = 1
a = 'b'
dir(C) would return
['__doc__', '__module__', 'a', 'i']
This is great, but notice how the order of 'a' and 'i' is now different then the order they were defined in.
How can I iterate over the attributes of C (potentially ignoring the built-in doc & module attributes) in the order they were defined? For the C class above, the would be 'i' then 'a'.
Addendum:
- I'm working on some serialization/logging code in which I want to serialize attributes in the order they were defined so that the output would be similar to the code which created the class.
I don't think this is possible in Python 2.x. When the class members are provided to the __new__ method they are given as a dictionary, so the order has already been lost at that point. Therefore even metaclasses can't help you here (unless there are additional features that I missed).
In Python 3 you can use the new __prepare__ special method to create an ordered dict (this is even given as an example in PEP 3115).
I'm new in python, so my solution may be not effective
class Q:
def __init__(self):
self.a = 5
self.b = 10
if __name__ == "__main__":
w = Q()
keys = w.__dict__.keys()
for k in keys:
print "Q.%s = %d"%(k,w.__dict__[k])
Output is:
Q.a = 5
Q.b = 10
put this method in your class
def __setattr__(self, attr, value):
if attr not in dir(self):
if attr == "__ordered_fields__":
super.__setattr__(self, attr, value)
else:
if not hasattr(self, "__ordered_fields__"):
setattr(self, "__ordered_fields__", [])
self.__ordered_fields__.append(attr)
super.__setattr__(self, attr, value)
and to get the fields in order, just do something like:
print(self.__ordered_fields__)
This information is not accessible, since attributes are stored in a dict, which is inherently unordered. Python does not store this information about order anywhere.
If you want your serialization format to store things in a certain order you would specify that order explicitly. You would not use dir, which contains things you don't know or care about, you would explicitly provide a list (or whatever) describing what to serialize.