Access class level attribute of another class? - python

I can access class-level attribute of a class (B) in method of another class (A) but I cannot access that at class-level of class A.
The issue can be resolved by defining B after A but why is this so and how can I access that keeping class B after class A.
I am looking for solution without class inheritance and without creating object of class B inside __init__ of class A.
See the code here:
class A:
a=B.b # This doesn't work
def __init__(self):
print(B.b) #This works
class B:
b=[1,2,3]

Assuming you don’t need to use the attribute while defining A (e.g., for a default argument), you can just assign it later:
class A:
def __init__(self):
print(B.b)
class B:
b=[1,2,3]
A.a=B.b
or even
class A:
def __init__(self):
print(B.b)
class B:
A.a=b=[1,2,3]
if you consider the classes so closely related that an assignment to one inside the other is less surprising than one outside both.

Related

Using subclass static property in base class

I have one base class and other classes inherit from this class (subclasses). There is one common method in base class that I want to use subclass static properties If subclass has the properties; otherwise default base class property should be used.
I have written following code to do such a thing:
class Base:
prp1 = 1
prp2 = 2
def __init__():
pass
def method1(self):
# print subclass prp1 and prp2 if exist (how to do this?)
class Subclass(Base):
prp1 = 3
prp2 = 4
a = Subclass()
a.method1() # should print subclass properties (3, 4)
How to get around this problem?
Thanks in advance.
Your code works just fine - you can reference prp1 and prp2 using self, so:
def method1(self):
print(self.prp1)
print(self.prp2)
Will reference the properties from the instance of the class you're calling it on.
Furthermore, if you don't define prp2 on the subclass, Python will fallback to prp2 from Base, which I assume is what you want.
Calling the class from instance should do the thing:
print(self.__class__.prp1)

Python official name for an attribute that is not a method

According to my understanding the data members of objects in Python are referred to as 'attributes'.
Attributes that are callable are referred to as an object's 'methods', but I couldn't find a name for non-callable attributes, such as val in the following example:
class C:
def __init__(self):
self.val = 42. # How would this be called?
def self.action():
"""A method."""
print(self.val)
I am sure different people may call val different things like 'field' or 'variable' but I am interested in an official name.
Surprisingly hard to find official information on this topic. After reading this article I do believe it should simply be called Class Variable and Instance Variable.
Attributes, Properties, Methods and Variables
Attribute is the collection name for the three names Property, Method and Variable. The latter two are prefixed by either Class or Instance. A property can only belong to the Class.
class Foo:
a = 1
def __init__(self):
self.b = 2
#property
def c(self):
return 3
#classmethod
def d(cls):
return 4
def e(self):
return 5
Foo.a # Class Attribute: Class Variable
Foo().a # Class Attribute: Class Variable
Foo().b # Instance Attribute: Instance Variable
Foo.c # Class Attribute: Property
Foo.d # Class Attribute: Class Method
Foo().d # Class Attribute: Class Method
Foo.e # Class Attribute: Class Method
Foo().e # Instance Attribute: Instance Method
Sources
Difference between Class and Instance methods
How do I assign a property to an instance in Python?
What's the difference between a Python "property" and "attribute"?
https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces
Diagram made in Creately
I'm not sure if one exists, but I'd suggest just "instance attribute".
Features about this naming:
It excludes methods. Methods are all callable class attributes, so this wording excludes all methods.
It includes callable instance attributes. Consider the following code:
class Container:
def __init__(self, item):
self.item = item
c = Container(x)
c.item # is an "instance attribute"
c.item == x # True
Note that c.item is an "instance attribute" regardless of whether or not it's callable. I think this is behaviour you're after, but I'm not sure.
It excludes non-callable class attributes, e.g.
class SomeClass:
x = 5 # Is not an "instance attribute"
It includes per-instance attributes, e.g.
obj.x = 5
obj.x # Is an "instance attribute"
In the end, all of these features may be positives or negatives depending on specifically what you want. But I don't know specifically what you want, and this is as close as I can get. If you can provide more information, I can give a better suggestion.

Access methods of member of Parent that references other module, from child

New to Python. Apologies for the title. Been searching for days on this problem :S
I am coming from a PHP background where I can create classes in their own files and then call those classes from anywhere as long as I have a reference to them.
For instance;
require class Z from class A.
Then have class B extend class A.
then be able to call methods on class Z from class B.
I want to have a parent class that contains methods and members that other classes can extend so that I'm not re-inventing the wheel every time I want create a class that is distinct in its own way, but also has similarities to other classes.
Maybe my understanding of how modules work in Python is wrong? Following is an example of what I'm trying to achieve. Do i need all of these classes in one module? Can someone explain the process for what I'm attempting to do?
import Z
class A():
def __init__(self):
self.varZ = Z()
self.some_value = None
def a_setter_function(self, value):
self.some_value = value
Then extending classes, for example class B through to class X;
import A
class B(A):
def some_function(self):
something = self.varZ.do_something_from_z_class()
def set_value(self, value):
self.a_setter_function(value)
Always raises;
'ClassB' object has no attribute 'varZ'
I have no issues in calling 'a_setter_function()' from class B.
Can also call methods on varZ from class A.
The only solution I can come up with is to have a method in class A (called from class B) which calls the method from class Z. ie The method I'm trying to call from Class B.
Why can't I call a method of class Z from class B via its parent class A?

How to change variable of main class from inherited class?

I need to change object variable directly from inherited class.
Here is my code example:
class A(object):
def __init__(self,initVal=0):
self.myVal = initVal
def worker(self):
self.incrementor = B()
self.incrementor.incMyVal(5)
class B(A):
def incMyVal(self,incVal):
super().myVal += incVal
obj = A(5)
print(obj.myVal)
obj.worker()
print(obj.myVal)
But it doesn't work:
AttributeError: 'super' object has no attribute 'myVal'
I also tried to use global/nonlocal keywords with my variable in B class, but no luck.
In my main case, the B class is an event handler. And it should change the attribute of an object when an event fires. So I'm not able to use return in the incMyVal method.
super() can only search for class attributes in the class MRO, not instance attributes. myVal is set on an instance of the class, not on a class itself.
There is only ever one instance; it doesn't matter if code from class A or a derived class is altering attributes on an instance, it is just one namespace.
However, in your case, you shouldn't even be using inheritance. You are trying to use an independent, second instance to alter the attributes of an instance of A. Class inheritance doesn't give you access to instances of the base class like this.
Refactor B to take an instance of A, then act on that instance:
class B:
def __init__(self, ainstance):
self.ainstance = ainstance
def incMyVal(self, incVal):
self.ainstance.myVal += incVal
Note that B is not a subclass of A here; it is not a (specialised) object of the same type at all; it is a different kind of thing, something that increments attributes of another object.
Pass in the instance when you create an instance of B:
def worker(self):
self.incrementor = B(self)
self.incrementor.incMyVal(5)
This does create a circular reference, which can keep objects alive for longer than perhaps needed. You may want to use a weak reference instead:
import weakref
class B:
def __init__(self, ainstance):
self.ainstance_ref = weakref.ref(ainstance)
def incMyVal(self, incVal):
ainstance = self.ainstance_ref()
if ainstance is not None:
ainstance.myVal += incVal
Now B instances only hold a weak reference to their A instance, and will do nothing if that instance no longer exists.

Python: Overriding a member with a property?

I was trying to override a member of a Python (2.7) class with a property, as shown in the following code:
class Base:
def __init__(self):
self.foo = 1
class Derived(Base):
foo = property(lambda self: 2)
print Derived().foo
However, the last line prints 1 instead of 2. From the way I thought properties are supposed to work (ie., easily change a member to a function later on), this seems counter-intuitive to me. Am I missing something? Is there some workaround?
This doesn't work because you aren't using a new-style class. Properties are descriptors which only work on new-style classes. What your code is doing is this:
You create a class Derived with a class attribute foo. Then when you create an instance of the class, Base.__init__ takes over since Derived has no __init__ and you add the instance attribute foo which takes precedence to the class attribute.
If you change:
class Base: #old style class
to:
class Base(object): #new style class
You'll run into an entirely new problem, mainly that your property doesn't have an appropriately defined setter, so when you do self.foo = 1 in Base.__init__ you'll get an AttributeError

Categories

Resources