Python3 , OOP : Multiple classes inheritance into single class - python

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.

Related

How to call a function within an attribute? [duplicate]

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>

Declaring several python classes in a loop?

I have a generic class definition, something like this -
class Foo(object):
property = 1
def __init__(self, ...):
...
I wish to create a large number of classes, each of which has a different value of property, and store these classes in a list. The classes in this list will be subsequently used to create several objects.
What is the best way to do this?
While I doubt that there isn't a better solution to whatever your underlying problem might be, you can create classes dynamically using type:
class Foo(object):
def __init__(self, x):
self.x = x
# class-name---vvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvv--class-attributes
klasses = [type('Foo{}'.format(n), (Foo,), {'property': n}) for n in range(5)]
# parent-classes ^^^^^^
klasses[4]
# <class '__main__.Foo4'>
klasses[4].property
# 4
inst = klasses[4]('bar')
inst.x
# 'bar'
c = []
for i in range(5):
class X(object):
property = i
def __init__(self):
print(self.property)
c.append(X)
c[0]() # will print 0
c[4]() # will print 4
But this has a bunch of drawbacks. I also think that the comment given below the question is remarkable. Very likely you strive for a solution which is not the best for your original problem.
If you really want to do it, then sure you can create classes dynamically using type
class BaseClass(object):
# the code that needs to be common among all classes
properties = [1, 2, 3]
classes = [type("class_{0}".format(i), (BaseClass,), {'property': property}) for i, property in enumerate(properties)]
However, you probably need to think about your design. I don't know about the problem you want to solve, but perhaps keeping the property variable as instance one would make more sense.
I think the best way would just be to iterate i=0 to n-1, appending a new object to the end of the list. You can then use i to index into the list and change the value of property that way.

iterate over an instance object's attributes in Python

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))

python - class instance variable inherence and class variable inherence

The code below:
Since Iter Class is inheriting the Parser class, class Iter(Parser):
is it unnessary to define duplicate but Iter class specific variables with Parser class variables?
Meaning
self.totalEntriesI is just receiver of the variable value in the Parser class known as totalEntires shown in the code as Parser.totalEntires so that work may be done with the value.
however is this necessary?
could I achieve the same thing with out doing it
class Iter(Parser):
def __init__(self, Parser):
self.totalEntriesI = Parser.totalEntries
self.perPageI = Parser.perPage
self.currentPageI = Parser.currentPage
Hugs and kisses
Correct, it's unneccesary. The class attributes ("variables") of Parser are also available on its subclass Iter.
If you assign them to instance attributes as shown, then each Iter instance will get its own copy of the values -- useful if you need to modify them later on a per-instance basis, but otherwise a waste of space and attention :)
A subtlety to be aware of: if you subsequently assign a value to one of these attributes via the subclass Iter, then Iter will get its own copy of the attribute. For example:
>>> class A(): my_attr = 'foo'
>>> class B(A): pass
As you'd expect,
>>> A.my_attr == B.my_attr == 'foo'
True
However, observe:
>>> B.my_attr = 'bar'
>>> B.my_attr
'bar'
>>> A.my_attr
'foo'

Best of two ways to declare a class variable in Python

The way I usually declare a class variable to be used in instances in Python is the following:
class MyClass(object):
def __init__(self):
self.a_member = 0
my_object = MyClass()
my_object.a_member # evaluates to 0
But the following also works. Is it bad practice? If so, why?
class MyClass(object):
a_member = 0
my_object = MyClass()
my_object.a_member # also evaluates to 0
The second method is used all over Zope, but I haven't seen it anywhere else. Why is that?
Edit: as a response to sr2222's answer. I understand that the two are essentially different. However, if the class is only ever used to instantiate objects, the two will work he same way. So is it bad to use a class variable as an instance variable? It feels like it would be but I can't explain why.
The question is whether this is an attribute of the class itself or of a particular object. If the whole class of things has a certain attribute (possibly with minor exceptions), then by all means, assign an attribute onto the class. If some strange objects, or subclasses differ in this attribute, they can override it as necessary. Also, this is more memory-efficient than assigning an essentially constant attribute onto every object; only the class's __dict__ has a single entry for that attribute, and the __dict__ of each object may remain empty (at least for that particular attribute).
In short, both of your examples are quite idiomatic code, but they mean somewhat different things, both at the machine level, and at the human semantic level.
Let me explain this:
>>> class MyClass(object):
... a_member = 'a'
...
>>> o = MyClass()
>>> p = MyClass()
>>> o.a_member
'a'
>>> p.a_member
'a'
>>> o.a_member = 'b'
>>> p.a_member
'a'
On line two, you're setting a "class attribute". This is litterally an attribute of the object named "MyClass". It is stored as MyClass.__dict__['a_member'] = 'a'. On later lines, you're setting the object attribute o.a_member to be. This is completely equivalent to o.__dict__['a_member'] = 'b'. You can see that this has nothing to do with the separate dictionary of p.__dict__. When accessing a_member of p, it is not found in the object dictionary, and deferred up to its class dictionary: MyClass.a_member. This is why modifying the attributes of o do not affect the attributes of p, because it doesn't affect the attributes of MyClass.
The first is an instance attribute, the second a class attribute. They are not the same at all. An instance attribute is attached to an actual created object of the type whereas the class variable is attached to the class (the type) itself.
>>> class A(object):
... cls_attr = 'a'
... def __init__(self, x):
... self.ins_attr = x
...
>>> a1 = A(1)
>>> a2 = A(2)
>>> a1.cls_attr
'a'
>>> a2.cls_attr
'a'
>>> a1.ins_attr
1
>>> a2.ins_attr
2
>>> a1.__class__.cls_attr = 'b'
>>> a2.cls_attr
'b'
>>> a1.ins_attr = 3
>>> a2.ins_attr
2
Even if you are never modifying the objects' contents, the two are not interchangeable. The way I understand it, accessing class attributes is slightly slower than accessing instance attributes, because the interpreter essentially has to take an extra step to look up the class attribute.
Instance attribute
"What's a.thing?"
Class attribute
"What's a.thing? Oh, a has no instance attribute thing, I'll check its class..."
I have my answer! I owe to #mjgpy3's reference in the comment to the original post. The difference comes if the value assigned to the class variable is MUTABLE! THEN, the two will be changed together. The members split when a new value replaces the old one
>>> class MyClass(object):
... my_str = 'a'
... my_list = []
...
>>> a1, a2 = MyClass(), MyClass()
>>> a1.my_str # This is the CLASS variable.
'a'
>>> a2.my_str # This is the exact same class variable.
'a'
>>> a1.my_str = 'b' # This is a completely new instance variable. Strings are not mutable.
>>> a2.my_str # This is still the old, unchanged class variable.
'a'
>>> a1.my_list.append('w') # We're changing the mutable class variable, but not reassigning it.
>>> a2.my_list # This is the same old class variable, but with a new value.
['w']
Edit: this is pretty much what bukzor wrote. They get the best answer mark.

Categories

Resources