Python Variable Access - python

class A:
def __init__(self):
self.i = 0
def demo(self):
self.a=1
class B(A):
def __init__(self, j = 0):
super().__init__()
self.j = j
print(self.i)
self.demo()
def demo(self):
print(self.a)
def main():
b = B()
print(b.i)
print(b.j)
main()
why am i not able to access self.a inside class b
does prefixing a variable with self. will make it an instance variable
Thanks

When you include a demo method for both classes, the most recently-defined one masks the others. Since you define B after you define A but before you call any of the methods in A, demo will try to access a variable that was never defined. You should either call demo within A (in __init__, probably), or change the name of demo in B to something unique, which will allow you to access both methods (probably the best approach, since they do different things and you want to make use of both).

Because you overwrite demo method on B class.
If you want to access self.a add it to __init__ method of A class or call parent demo method like this:
def demo(self):
super().demo()
print(self.a)

It is because instance variable b is not initiated within __init__ of A

Because class A.demo() is not executed:
class A:
def init(self):
self.i = 0
def demo(self):
self.a=1
class B(A):
def __init__(self, j = 0):
super().__init__()
self.j = j
print(self.i)
super().demo()
self.demo()
def demo(self):
print(self.a)
def main():
b = B()
print(b.i)
print(b.j)
main()

Related

Inheritance using a function as the base object constructor

I've imported a package that provides me with a class and a wrapper function that creates an instance of that class.
For example:
class Foo:
def __init__(self, a, b):
self.a = a
self.b = b
def print_a(self):
print(self.a)
def print_b(self):
print(self.b)
def makeFoo(x, y):
a = x + y
b = x - y
return Foo(a, b)
I want to have a similar class NamedFoo, that has the same properties/methods, also has a name property, and with a constructor that calls makeFoo. I figure that this should be solved using inheritance, with NamedFoo being a subclass of Foo. However, I don't know how to make the NamedFoo constructor utilize makeFoo correctly:
class NamedFoo(Foo):
def __init__(self, x, y, name):
# ???
# Foo = makeFoo(x, y) ??
# self.Foo = makeFoo(x, y) ??
self.name = name
def printName(self):
print(self.name)
Example data:
myNamedFoo = NamedFoo(2,5,"first")
myNamedFoo.print_a() # (From makeFoo: a = x + y) ==> 2 + 5 = 7
myNamedFoo.print_b() # (From makeFoo: a = x - y) ==> 2 - 5 = -3
I'm not too familiar with object-oriented programming, so I might just be using the wrong search terms, but I haven't found anything similar to what I need. Is this possible, and if so how can I do it?
I'm also not sure if this is an X/Y problem, but here are the alternatives I've considered and why I don't think they're ideal:
Composition of Foo and the property name: It's ugly and doesn't seem right.
Manually adding the name property to each Foo object, and perhaps wrapping it in a function: Doesn't quite have the elegance of a one liner constructor.
Rewriting the constructor for the Foo class, to have the same code as what's in makeFoo: makeFoo is rather complex and needs to do a lot of setup, and this would in any case lead to code duplication
In the NamedFoo constructor, create an instance of the Foo class from the makeFoo wrapper function. Pass this instance's attributes to the super().__init__.
class NamedFoo(Foo):
def __init__(self, x, y, name):
_foo = makeFoo(x,y) # use the wrapper to handle complex logic from input params
super().__init__(_foo.a,_foo.b) # pass the properly derived Foo attributes to the superclass constructor
self.name = name
This way, we're instantiating NamedFoo from whatever magic happens within the makeFoo function. Pass your x and y to that, which creates a throwaway Foo instance (so we can have it properly constructed with whatever complex logic resides in the helper function). The final NamedFoo class is then instantiated from the Foo constructor.
i think this should work..
class Foo:
def __init__(self,a,b):
self.a = a + b
self.b = a - b
def print_a(self):
print(self.a)
def print_b(self):
print(self.b)
class NamedFoo(Foo):
def __init__(self,a,b,name):
super().__init__(a,b)
self.name = name
def main():
example = NamedFoo(2,5,"first")
example.print_a()
example.print_b()
main()
this prints out
7
-3
or if you really want to use a function to create self.a and self.b use this:
class Foo:
def __init__(self, a, b):
self.a, self.b = make_foo(a,b)
def print_a(self):
print(self.a)
def print_b(self):
print(self.b)
class NamedFoo(Foo):
def __init__(self, a,b,name):
super().__init__(a,b)
self.name = name
def make_foo(x,y):
return x+y, x-y
def main():
example = NamedFoo(2,5,"first")
example.print_a()
example.print_b()
main()

Newbie Debugging a Python Code

I want local variable of a class to be changed by other class. My script is similar to the following :
import datetime
b = []
class P:
def __init__(self):
self.count = 1
self.create()
def create(self):
global b
a = C(self.count)
for i in range(10):
a.print_name()
print b
class C:
def __init__(self, *data):
self.test = data[0]
#staticmethod
def print_name():
global b
b.append(datetime.datetime.now())
o = P()
How to avoid use of a global variable . On web i found use of "super " can resolve the issue . Please help in this regard .
Make C constructor to accept P instance. And call the method of P to append item to instance attribute of P object.
class P:
def __init__(self):
self.count = 1
self.items = []
self.create()
def append(self, item):
self.items.append(item)
def create(self):
a = C(self, self.count) # <-- Pass P instance (self)
for i in range(10):
a.print_name()
print self.items
class C:
def __init__(self, p_instance, *data):
self.p_instance = p_instance # <-- Save P instance to use later
self.test = data[0]
def print_name(self):
self.p_instance.append(datetime.datetime.now()) # <-- Call p instance method
You are probably looking for a class attribute. If you add b as an attribute to the C class, it can be accessed as C.b and C().b, i.e. from a reference to the class or any instance.
class C(object): # classes in py2 should inherit from object!
b = [] # b inside C definition
#classmethod
def print_name(cls):
cls.b.append(datetime.datetime.now())
class P(object):
def __init__(self):
self.count = 1
self.create()
def create(self):
a = C(self.count)
for i in range(10):
a.print_name()
print C.b # or a.b
Of course, you can also place b on P. In this case, do
def print_name():
P.b.append(datetime.datetime.now())

Accidentally calling an ovverriden method from base class's __init__

This program seems to do everything by the book, yet this issue cropped up: while a base class was being init'ed a member method was called that is overriden in the derived class and assumes that the derived class has been constructed.
Is there some best practice to protect against this?
#!/usr/bin/env python3
class A:
def __init__(self):
self.ax = 1
print(self)
def __repr__(self):
return "{} ax: {}".format(self.__class__.__name__, self.ax)
class B(A):
def __init__(self):
super().__init__()
self.bx = 10
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
if __name__ == "__main__":
B()
And here's the error:
AttributeError: 'B' object has no attribute 'bx'
Generally, unless you really know what you are doing, you want to call the superclass initialization after everything your class needs to do is done. Same with this example, repr is trying to print self.bx before you initialize it. If you do
class B(A):
def __init__(self):
self.bx = 10
super().__init__()
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
it works as expected
Edited:
Instead of doing computation on __init__, one idea may be to do that in a factory function/classmethod.
Example instead of doing:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
self.initialize()
def initialize(self):
# do some things
Do:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
#classmethod
def from_a_b(cls, a, b):
instance = cls(a, b)
instance.initialize()
return instance

Python scope inside a nested function inside a class?

How can I set a class variable from inside a function inside another function?
var.py
class A:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def seta(self):
def afunction():
self.a = 4
afunction()
def geta(self):
return self.a
run.py
cA = A()
print cA.a
cA.seta()
print cA.a
print cA.geta()
python run.py
1
1
1
why does a not equal 4 and how can I make it equal 4?
Edit:
Thanks everyone - sorry, I just saw now. I accidentally was off by a _ in one of my names.... so my scope is actually all ok.
The problem is that there are multiple self variables. The argument passed into your inner function overwrites the scope of the outer.
You can overcome this by removing the self parameter from the inner function, and making sure you call that function in some way.
class A:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def seta(self):
def afunction(): # no self here
self.a = 4
afunction() # have to call the function
def geta(self):
return self.a
As others have mentioned, afunction is never called. You could do something like this:
class A:
def __init__(self):
self.a = 1
def seta(self):
def afunction(self):
self.a = 4
afunction(self)
def geta(self):
return self.a
a = A()
print a.a
a.seta()
print a.a
Here we actually call afunction and explicitly pass it self, but this is a rather silly way to set the attribute a -- especially when we can do it explicitly without the need for getters or setters: a.a = 4
Or you could return the function:
def seta(self):
def afunction(): #Don't need to pass `self`. It gets picked up from the closure
self.a = 4
return afunction
and then in the code:
a = A()
a.seta()() #the first call returns the `afunction`, the second actually calls it.
Inside seta, you define a function
def afunction(self):
self.a = 4
...that would set self.a to 4 if it would ever be called. But it's not called anywhere, so a is unchanged.
As several others have said, you need to actually call functiona at some point. Comments won't let me type this intelligably so here's an answer:
def seta(self):
def functiona(self): #defined
self.a = 4
functiona() #called
How can you make it equate to 4:
class A:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def seta(self):
##def afunction(self): (remove this)
self.a = 4
def geta(self):
return self.a
Tricky part: Why does is not equate to 4...
Currently a is set to 4 only via "afunction". Since afunction is never called it never executes.. The seta has "afunction" nested inside but not called... similar to member variables within a classs.

Is it Possible to rewrite the getter of a property in a subclass?

For example:
class Example:
def __init__(self):
self.v = 0
#property
def value(self):
return self.v
#value.setter
def value(self, v):
self.v = v
class SubExample(Example):
pass
Would it be possible to rewrite just the getter to value in SubExample?
You can do so like this
class DoubleExample(Example):
#Example.value.getter
def value(self):
return self.v * 2
o = Example()
o.value = 1
print o.value # prints "1"
p = DoubleExample()
p.value = 1
print p.value # prints "2"
However, this only works if Example is a new-style class (class Example(object):) rather than an old style class (class Example:), as it is in your example code.
Warning: Thomas pointed out in the comments that this method may not behave as expected if you're using multiple inheritance (class Foo(Bar, Baz)).
It isn't possible to override a property's getter in a subclass, no. The property is an object that lives in the class and that holds references to the functions you give it -- if you later redefine the names of those functions, it won't affect the property at all.
What you can do is have the functions your property calls perform indirect calls, like so:
class Example(object):
def __init__(self):
self.v = 0
#property
def v(self):
return self._v_getter()
#v.setter
def v(self, value):
return self._v_setter(value)
def _v_setter(self, value):
self._v = value
class SubExample(Example):
def _v_getter(self):
return 5
>>> se = SubExample()
>>> se.v
5
>>> se._v
0
>>> se.v = 10
>>> se.v
5
>>> se._v
10
Alternatively, you can redefine the entire property in the subclass, by simply defining a new property. You won't have convenient access to the functions or property defined in the parentclass, however, and doing the right thing in the face of multiple inheritance is difficult.
Your question has been answered before:
http://code.activestate.com/recipes/408713-late-binding-properties-allowing-subclasses-to-ove/
http://stackoverflow.com/questions/3393534/python-property-and-method-override-issue-why-subclass-property-still-calls-the
Essentially, instead of using property directly, you have to defer calling the getter so that it will access the one defined in the subclass rather than the one defined in the superclass when you first defined the property. This can be achieved via a lambda:
class Test(object):
def __init__(self):
self.v = 0
def _value(self):
return self.v
def _value_setter(self, v):
self.v = v
value = property(lambda self: self._value(), lambda self, v: self._value_setter(v))
class Test2(Test):
def _value(self):
return self.v + 1
a = Test()
a.value = 2
print a.value # 2
b = Test2()
b.value = 2
print b.value # 4

Categories

Resources