How to print a variable from a derived class? - python

I know there are similar questions on this topics but none of them seem to apply to my case
Why would the following code print None and not True?
Thanks
class A(object):
flag = None
#classmethod
def set_flag(cls):
cls.flag = True
class B(A):
#classmethod
def print_super_flag(cls):
print cls.__bases__[0].flag # This prints None
print super(B, cls).flag # This also
if __name__ == "__main__":
b = B()
b.set_flag()
b.print_super_flag()

This call:
b.set_flag()
You defined set_flag as:
#classmethod
def set_flag(cls):
cls.flag = True
So when b calls set_flag, cls is B - so it sets B.flag, not A.flag. Then when you go to print A.flag, it is None because you never touched it. So your issue is not at all in print_super_flag - you access A.flag correctly there. Twice.
If instead you defined set_flag as:
class A(object):
flag = None
#classmethod
def set_flag(cls):
A.flag = True
Your code prints out True (twice), because set_flag now sets A.flag in derived classes. Of course at this point your method being a classmethod is moot, but that's a function of how you expect the method to perform; when you call a classmethod from a derived class, cls is that derived class, not the parent class.

Try this slightly extended version to see what's going on:
class A(object):
flag = None
#classmethod
def set_flag(cls):
cls.flag = True
class B(A):
#classmethod
def print_super_flag(cls):
print cls.__bases__[0].flag # This prints None
print super(B, cls).flag # This also
if __name__ == "__main__":
b = B()
b.set_flag()
print b.flag
b2 = B()
print b2.flag
a = A()
print a.flag
Prints:
True # because you set b.flag
True # because b.flag and b2.flag refer to the same class variable, B.flag
None # because B.flag and A.flag are NOT the same class variable
Basically, the child class (B) has its own copy of the flag class variable, rather than sharing it with the parent class (A).
More details here, assuming you're using Python 2.7-ish.

If you only want there to only one flag attribute that's part of the base class, you need to change the set_flag() method to:
class A(object):
flag = None
#classmethod
def set_flag(cls):
A.flag = True
Since the revised method doesn't reference its cls argument, you could just make it staticmethod and remove the argument, although that's not extremely important. Regardless, by hardcoding the base class, you ensure which flag attribute is being set, otherwise another flag attribute will be created as part of cls argument, which is the class the call was made through.
Since only one class attribute exists, its value will be printed.

Related

How to create custom type validation function in Python? [duplicate]

I am using python 2.7.3 on Windows. I tried to override the __instancecheck__ magic method as a class method. But I can not make it work.
class Enumeration(int):
#classmethod
def __instancecheck__(cls, inst):
if type(inst) == cls:
return True
if isinstance(inst, int) and inst in range(0,10):
return True
return False
print isinstance(1, Enumeration) # prints False
print isinstance(1, Enumeration()) # prints True
I assume the first print statement would get True. But it seems the magic method __instancecheck__ is not called. And I don't know why the second print statement can work since the isinstance should take a class/type as the second parameter.
Does anyone know what the problem is? Thanks.
instancecheck must be defined in a metaclass:
class Enumeration(type):
def __instancecheck__(self, other):
print 'hi'
return True
class EnumInt(int):
__metaclass__ = Enumeration
print isinstance('foo', EnumInt) # prints True
Why is that? For the same reason why your second example worked. When python evaluates isinstance(A, B) it assumes B to be an object, looks for its class and calls __instancecheck__ on that class:
isinstance(A, B):
C = class-of(B)
return C.__instancecheck__(A)
But when B is a class itself, then its class C should be a class of a class, in other words, a meta-class!
The docs say:
Note that these methods are looked up on the type (metaclass) of a class. They cannot be defined as class methods in the actual class. This is consistent with the lookup of special methods that are called on instances, only in this case the instance is itself a class.
http://docs.python.org/2/reference/datamodel.html#customizing-instance-and-subclass-checks

Python: Why does class variable get assigned?

Here is my code:
class MyClass:
def __init__(self):
self.value = 0
def set_value(self, value):
self.value = 5
def get_value(self):
return self.value
value = print("Hello")
a = MyClass()
The output is:
Hello
What I do not understand is why print("Hello") gets executed. When I create an instance of the class only the instance variable is set to 0. Why self.value = 0 calls value = print("Hello")?
Can someone explain me this behavior?
The code evaluates the class when you execute it, and calls the print to define the class variable value.
The below example shows that it's printed before the instanciation.
class MyClass:
def __init__(self):
self.value = 0
def set_value(self, value):
self.value = 5
def get_value(self):
return self.value
value = print("Hello")
print('hi')
a = MyClass()
#output
>>> Hello
>>>hi
It doesn't. That print is executed because it's at the class level itself; the body of a class is executed at the time the class is defined. You would get that output even if you never instantiated MyClass.
Don't let the indentation trick you. value is not an instance variable. value is a class variable because it is defined in the class's scope. It's the same as doing:
class MyClass:
value = print("Hello")
....
Which means that the call to print will run at class definition time. In other words, when Python defines MyClass it also defines all of the class level variables - including value. To define value, it then calls print, which is why Hello is printed before you create an instance of MyClass.
If you want only instances of MyClass to print Hello, put the variable definition inside of the class constructor.
Side note: The print function returns None, so it's seems a bit strange that your assigning the value to a variable. Perhaps you were looking for something like input instead?
It does not, drop a = MyClass() and it will print "Hello" anyway. It executes code in the body when a class is defined:
class MyClass:
print(2 * 2)
# prints 4

Running super().__init__(value) where value is an #property

I'm just trying to grok how exactly Python handles this behind the scenes. So take this code snippet (from Effective Python by Brett Slatkin):
class Resistor(object):
def __init__(self, ohms):
self.ohms = ohms
self.voltage = 0
self.current = 0
class VoltageResistor(Resistor):
def __init__(self, ohms):
super().__init__(ohms)
self._voltage = 0
#property
def ohms(self):
return self._ohms
#ohms.setter
def ohms(self, ohms):
if ohms <= 0:
raise ValueError('{o} ohms must be > 0'.format(o=ohms))
self._ohms = ohms
#property
def voltage(self):
return self._voltage
#voltage.setter
def voltage(self, voltage):
self._voltage = voltage
self.current = self._voltage / self.ohms
VoltageResistor(-1) # fails
Running the super() call invokes the property check so that you can't instantiate with a zero or negative value. What is confusing me to me is that I would think that since the the __init__(ohms) call is being ran on the superclass, shouldn't it be in a different scope (the scope of the superclass) and thus exempt from invoking the #property check?
Scope doesn't come into play when working with object's attributes. Consider the following:
class A(object):
def __init__(self):
self.a = 1
def foo():
a = A()
a.a = 2
return a
def bar(a):
print(a.a)
bar(foo())
This example code will print 2. Note that within the scope of bar, there is no way to gain access to the scope of foo or even A.__init__. The class instance is carrying along all of it's attributes/properties with it (and a reference to it's class which has a reference to it's superclass, etc).
In your code, when you call VoltageResistor, an instance of VoltageResistor is created and passed to __init__ as self. When you call super.__init__(self), that VoltageResistor instance is passed along to Resistor.__init__. When it does self.ohms = ohms, python sees that self.ohms resolves to a property and you get the error. The tl;dr; here is that self is an instance of VoltageResistor and when working with attributes, the object on which the attributes are accessed is what is important, not the current scope).
To supplement the above excellent answer, just add the following line in the parent's constructor to get a better idea of what is going on:
class Resistor(object):
def __init__(self, ohms):
print (type(self).__name__)
self.ohms = ohms
It will print VoltageResistor and then throw a ValueError. The Python docs confirm this:
If c is an instance of C, c.x will invoke the getter, c.x = value will invoke the setter and del c.x the deleter.
ValueError Happens there because VoltageResistor.__init__ calls Resistor.__init__, which assigns self.ohms = -1. That assignment causes the #ohms.setter method from VoltageResistor to be called, and it immediately runs the validation code before object construction has completed.

How to override a method of a member object?

In python 3.4 I have a member object through composition.
I would like to override one of it's member functions.
def class Foo:
def __init__(self, value):
self.value = value
def member_obj.baz(baz_self, arg):
print("my new actions on {}".format(arg))
Foo.member_obj.baz(arg) #the original function
foo_inst = Foo(2)
bar = Bar(*bar_parameters) #from a third party module
setattr(foo_inst, "member_obj", bar) #it did not "stick" when I did foo_inst.member_obj = bar
foo_inst.member_obj.baz("some argument")
It does not make sense to inherit from the Bar class.
I also only want this different behaviour to occur if the object is inside Foo. I use Bar in many other places and would like to retain the same way of calling the method. I.e. I would like to avoid wrapping it in Foo.baz.
Is it even possible to do something like the def member_obj.baz and is it a good idea?
It would be similar to this: https://softwareengineering.stackexchange.com/questions/150973/what-are-the-alternatives-to-overriding-a-method-when-using-composition-instea
Are you trying to do something like this?
class B():
def __init__(self):
self.x = None
def fun(self):
print("Assigning value to attribute of object of class B.\n")
self.x = "Value of B object's attribute"
class A():
def __init__(self):
self.value = B()
def fun(self):
print("Screw this, I'll do something else this time!\n")
self.value.x = 13
def override(self):
# Edit: you can assign any identifier (that is not reserved) to
# any type of object or method AND the "fun" ("really self.fun")
# above is visible from here, since we passed "self" as an
# argument
self.value.fun = self.fun
myObj = B()
myOtherObj = A()
myOtherObj.override()
myObj.fun()
myOtherObj.value.fun()

Naming conventions for class method vs instance method

I have two methods, one for the individual Instance, and one for every Instance in that class:
class MasterMatches(models.Model):
#classmethod
def update_url_if_any_matches_has_one(cls):
# apply to all instances, call instance method.
def update_url_if_any_matches_has_one(self):
# do something
Should I name these the same? Or, what is a good naming convention here?
The question of using the same names can be clarified by understanding how decorators work.
#dec
def foo(x):
print(x)
translates to
def foo(x):
print(x)
foo = dec(foo)
In your example the decorator syntax can be expanded to
class MasterMatches(models.Model):
def update_url_if_any_matches_has_one(cls):
# apply to all instances, call instance method.
update_url_if_any_matches_has_one = classmethod(update_url_if_any_matches_has_one)
def update_url_if_any_matches_has_one(self):
# do something
The former implementation of update_url_if_any_matches_has_one will be overwritten by the latter.
Usually use self declaration style. #classmethod use only if method not works with class instance fields.
Function decorated as #classmethod takes the first argument is the class type, while normal method takes instance of object.
class A:
#classmethod
def a(cls):
print(cls)
def b(self):
print(self)
a = A()
a.a()
a.b()
# Output:
# <class '__main__.A'>
# <__main__.A object at 0x03FC5DF0>
It can be useful if you have a static class fields. The to access therm you don't need explicitly specify the class name. But you don't get access to instance fields. Example:
class A:
field = 1
#classmethod
def a(cls):
print(cls.field)
def b(self):
self.field = 2
print(self.field, A.field)
a = A()
a.a()
a.b()
# Outputs:
# 1
# 2 1

Categories

Resources