I have a class
class MyClass():
def __init__(self):
self.a = 7
self.b = 2
#property
def aAndB(self):
return self.a + self.b
I would like a function that iterates over all properties and returns only class instances having a certain property.
My goal is a function like this:
def findInstances(listOfInstances, instanceVariable, instanceValue):
#return all instances in listOfInstances where instanceVariable==instanceValue
Using instance.__dict__ only gives me a and b, but not aAndB. I would like to have a dict of all properties/methods with their values to loop over, so I can search for instances where a certain property (or method decorated with #property) has a certain value.
Currently, calling the function like this
findInstances(someListOfInstances, 'aAndB', '23')
makes Python complain that aAndB is not in instance.__dict__.
Maybe all of you are right and the answers are there, but I still don't get it. All the answers in the mentioned questions get lists, not dictionaries. I want all the properties (including methods with the #property decorator) and their values. Is there a way to iterate over the values of the keys in dir(myClass)? The dir command only contains the names of the attributes, not their values.
I need something like
for a in dir(myClass):
print a, myClass.(a) # get the value for an attribute stored in a variable
To be even more clear: The following achieves exactly what I want but there is probably a better way that I don't know.
for a in dir(myClass):
print a, eval("myClass.{}".format(a))
There's actually a very simple way to do this, using getattr in place of eval:
myClass = MyClass()
for a in dir(myClass):
if(a[:2] != "__"): #don't print double underscore methods
print a, getattr(myClass, a)
Output:
a 7
aAndB 9
b 2
This has the very big advantage of not needing to hard code in the name of your instance into the string, as is required using eval("myClass.{}".format(a))
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 3 years ago.
I have a Python class that have attributes named: date1, date2, date3, etc.
During runtime, I have a variable i, which is an integer.
What I want to do is to access the appropriate date attribute in run time based on the value of i.
For example,
if i == 1, I want to access myobject.date1
if i == 2, I want to access myobject.date2
And I want to do something similar for class instead of attribute.
For example, I have a bunch of classes: MyClass1, MyClass2, MyClass3, etc. And I have a variable k.
if k == 1, I want to instantiate a new instance of MyClass1
if k == 2, I want to instantiate a new instance of MyClass2
How can i do that?
EDIT
I'm hoping to avoid using a giant if-then-else statement to select the appropriate attribute/class.
Is there a way in Python to compose the class name on the fly using the value of a variable?
You can use getattr() to access a property when you don't know its name until runtime:
obj = myobject()
i = 7
date7 = getattr(obj, 'date%d' % i) # same as obj.date7
If you keep your numbered classes in a module called foo, you can use getattr() again to access them by number.
foo.py:
class Class1: pass
class Class2: pass
[ etc ]
bar.py:
import foo
i = 3
someClass = getattr(foo, "Class%d" % i) # Same as someClass = foo.Class3
obj = someClass() # someClass is a pointer to foo.Class3
# short version:
obj = getattr(foo, "Class%d" % i)()
Having said all that, you really should avoid this sort of thing because you will never be able to find out where these numbered properties and classes are being used except by reading through your entire codebase. You are better off putting everything in a dictionary.
For the first case, you should be able to do:
getattr(myobject, 'date%s' % i)
For the second case, you can do:
myobject = locals()['MyClass%s' % k]()
However, the fact that you need to do this in the first place can be a sign that you're approaching the problem in a very non-Pythonic way.
OK, well... It seems like this needs a bit of work. Firstly, for your date* things, they should be perhaps stored as a dict of attributes. eg, myobj.dates[1], so on.
For the classes, it sounds like you want polymorphism. All of your MyClass* classes should have a common ancestor. The ancestor's __new__ method should figure out which of its children to instantiate.
One way for the parent to know what to make is to keep a dict of the children. There are ways that the parent class doesn't need to enumerate its children by searching for all of its subclasses but it's a bit more complex to implement. See here for more info on how you might take that approach. Read the comments especially, they expand on it.
class Parent(object):
_children = {
1: MyClass1,
2: MyClass2,
}
def __new__(k):
return object.__new__(Parent._children[k])
class MyClass1(Parent):
def __init__(self):
self.foo = 1
class MyClass2(Parent):
def __init__(self):
self.foo = 2
bar = Parent(1)
print bar.foo # 1
baz = Parent(2)
print bar.foo # 2
Thirdly, you really should rethink your variable naming. Don't use numbers to enumerate your variables, instead give them meaningful names. i and k are bad to use as they are by convention reserved for loop indexes.
A sample of your existing code would be very helpful in improving it.
to get a list of all the attributes, try:
dir(<class instance>)
I agree with Daenyth, but if you're feeling sassy you can use the dict method that comes with all classes:
>>> class nullclass(object):
def nullmethod():
pass
>>> nullclass.__dict__.keys()
['__dict__', '__module__', '__weakref__', 'nullmethod', '__doc__']
>>> nullclass.__dict__["nullmethod"]
<function nullmethod at 0x013366A8>
I want to call a function from a class A inside another class B. However, it should be called for an object of A. I mean if I have something like this:
class A:
def __init__(self, ....):
self.valuechanged=False
# do something
objectfromb=B()
self.somearray.append(objectfromb)
def updateevent(self):
self.valuechanged=True
# do some things if update event triggered
class B:
def __init__(self,...):
self.somevalue=0
self.someothervalue=1
# do something
def updatesomevalue(self,somenewvalue):
self.somevalue=somenewvalue
# !!! HERE SHOULD BE A CALL TO CLASS A FUNCTION updateevent
And in my code I use the classes like this:
a=A()
Then i would have a list somearray in a (a.somearray) which contains an object of B. So if I want to update this object B with:
a.somearray[0].updatesomevalue(10)
Then there should not only be a new value for a.somearray[0].somevalue but also the function update event of class A should trigger changing a. How can I do that?
There are two ways I can think of to achieve this without invoking any special magic.
The first is to have objects of type B know what object A they belong to so that they can call updateevent on it. This isn't a way I'm generally a fan of as there's extra admin work to do when moving instances of B between instances of A and such. If that's not a concern then it may be the best way. You'd do that something like this (with a method on A to create a B and set the correct parent for convenience):
class A:
valuechanged=False
somearray=[]
def add_b(self):
b = B(self)
somearray.append(b)
return b
def updateevent(self):
self.valuechanged=True
class B:
somevalue=0
someothervalue=1
def __init__(self, parent):
self.parent = parent
def updatesomevalue(self,somenewvalue):
self.somevalue=somenewvalue
self.parent.updateevent()
The second is to provide a method on A that does both tasks. This is only suitable if 1) you know A will always contains instances of B and only B and 2) B's interface is relatively small (to avoid providing lots of methods of this type on A). You would implement this as something like:
class A:
valuechanged=False
somearray=[]
def updatesomevalue(self, index, new_value):
somearray[index].updatesomevalue(new_value)
self.updateevent()
def updateevent(self):
self.valuechanged=True
class B:
somevalue=0
someothervalue=1
def updatesomevalue(self,somenewvalue):
self.somevalue=somenewvalue
Something I haven't addressed is that somearray, somevalue, etc are all being created as class attributes in your example (i.e. they will be shared among all instances, instead of each instance having its own ones). This is likely not what you wanted.
I am Inheriting from multiple parent classes into a single class. What I am trying to do is make a situation of object data conflict.
I mean if two classes hold a variable with same name and different data, which data will be loaded by Python if that variable comes to picture?
what I did
>>> class pac:
... var=10
... var2=20
...
>>> class cac:
... var3=30
... var2=10
...
>>> pob=pac()
>>> cob=cac()
>>> pob.var
10
>>> pob.var2
20
>>> cob.var2
10
>>> cob.var3
30
>>> class newclass(pac,cac):
... def sum(self):
... sum=self.var+self.var2
... sum2=self.var2+self.var3
... print(sum)
... print(sum2)
...
30
50
>>> nob.var
10
>>> nob.var2
20
>>> nob.var3
30
>>>
It seems like var2 data will consider from parent class : pac instead of cac class.
What needs to be done to make Python consider data from cac instead of pac if same variable name existed with different data? Please do not suggest me to change order of inheritance.
Thank you.
Without changing the order of inheritance, your subclass will always get an attribute it can find in the first class, from the first class. If you want to find out what the corresponding value is in the second class, you're going to have to explicitly ask for the second class's value.
In your case, something like
class newclass(pac,cac):
#property
def var2(self):
return cac.var2
Note that I'm explicitly asking for cac's var2.
You can set self.var2=cac.var2 in the newclass's init method:
class newclass(pac, cac):
def __init__(self):
self.var2 = cac.var2
You could also return a list/tuple of the possible values by using the following code:
#property
def var2(self):
key='var2'
return [getattr(c,key) for c in self.__class__.mro()[1:-1] if hasattr(c,key)]
The mro method returns a list of classes, the first one will be the callers class followed by parents and lastly the object built-in class.
This code will return a list of values in the order of inheritance.
Suppose you have two classes, A and B. Class B is defined inside the class A. I want to access the variables and methods of the outer class while inside the inner class. The code here is a toy example but has the essentials of what I want to demonstrate:
class A:
a = 'even'
b = 'odd'
class B:
def __init__(self, n):
if n%2 == 0: self.num = a
if n%2 == 1: self.num = b
self.description = A.desc()
def __getitem__(self, i):
return self.B(i)
def desc(self):
return a + '-' + b
>>> c = A()
>>> d = c[4]
>>> TypeError: unbound method desc() must be called with A instance as first argument (got nothing instead)
Here the method desc does some work on the variables of the class A and produces output. Class A is initialized correctly and you can access the variables a and b, even from the inner scope, given that you don't define the description variable. However, I cannot find a way to call the outer scope class methods desc. Is it possible to use the method desc in B without instantiating class A?
Explanation on why I use such a pattern:
Variables a and b in my program are rather big. I only need to initialize them once. In addition, I don't want these variables to float around in the program but to be only accessible to the inner class. Adding to all these is the fact that I can use the A.__getitem__ to extract 'slices' of the big data when needed. So the outer class provides me with hiding/encapsulation of the data, the indexing operator (through __getitem__) and all the routines required for extraction of slices of data (here the method desc. The inner class, B, provides the bundling of useful information from the big data for each index. This, most likely, is not the optimal design for achieving the described task. I am open and eager to hear your opinion regarding the alternative patterns.
I can't see any reason for you to be using classes here, let alone nested ones. In any case, there is almost never a reason to nest classes in Python, since inner classes don't get any special access to the outer class.
However if you want to allow anything to access a method without instantiating the object, you can make it a classmethod:
#classmethod
def desc(self):
return a + '-' + b
But I can't see why you would do any of this. Also, nothing here is a closure.
I need to iterate over a number of attributes inside an object. Each attribute is initialized as None and over the course of the program each will store a separate object. There are 16 attributes that I need to iterate over and the condition is that the attributes will store objects in a predetermined sequence. For example, if attribute 10 is empty, then attributes 11 to 16 will also be empty, therefore I will not need to iterate past any empty attributes. My initial result was to use 'if' statements for each attribute like this:
Class Object1:
def __init__(self):
self.attribute1=None
self.attribute2=None
self.attribute3=None
self.attribute4=None
...
def repeating_function(self):
if self.attribute1!=None:
self.attribute1.attribute=Callback1
if self.attribute2!=None:
self.attribute2.attribute=Callback2
if self.attribute3!=None:
self.attribute3.attribute=Callback3
...
But, because of the sequence in which the attributes store objects, I ended up with this:
class Object1:
def __init__(self):
self.attribute1=None
self.attribute2=None
self.attribute3=None
self.attribute4=None
self.attribute5=None
def repeating_function(self):
if self.attribute1!=None:
self.attribute1.attribute=Callback1
if self.attribute2!=None:
self.attribute2.attribute=Callback2
if self.attribute3!=None:
self.attribute3.attribute=Callback3
...
Basically, my question is: if the second example is more efficient at iterating over the non-empty attributes. Because I'm adding conditions inside conditions in the second example, I'm not sure which method is more efficient.
You should use a list instead of separate attributes:
class MyClass(object):
def __init__(self):
self.attributes = []
With this,
to add an attribute, use self.attributes.append(...);
to find out how many (non-None) attributes there are, use len(self.attributes);
to refer to the final non-None attribute, use self.attributes[-1];
and so on.