super() gives an error in Python 2 - python

I just started learning Python and I don't quite understand where the problem in this code is. I have a base class Proband with two methods and I want to create a subclass Gesunder and I want to override the attributes idn,artefakte.
import scipy.io
class Proband:
def __init__(self,idn,artefakte):
self.__idn = idn
self.artefakte = artefakte
def getData(self):
path = 'C:\matlab\EKGnurbild_von Proband'+ str(self.idn)
return scipy.io.loadmat(path)
def __eq__(self,neueProband):
return self.idn == neueProband.idn and self.artefakte == neueProband.artefakte
class Gesunder(Proband):
def __init__(self,idn,artefakte,sportler):
super().__init__(self,idn,artefakte)
self.__sportler = sportler
hans = Gesunder(2,3,3)

You have 2 problems in your code. In python 2:
super() takes 2 arguments: the class name, and the instance
in order to use super(), the base class must inherit from object
So your code becomes:
import scipy.io
class Proband(object):
def __init__(self,idn,artefakte):
self.__idn = idn
self.artefakte = artefakte
def getData(self):
path = 'C:\matlab\EKGnurbild_von Proband'+ str(self.idn)
return scipy.io.loadmat(path)
def __eq__(self,neueProband):
return self.idn == neueProband.idn and self.artefakte == neueProband.artefakte
class Gesunder(Proband):
def __init__(self,idn,artefakte,sportler):
super(Gesunder, self).__init__(idn,artefakte)
self.__sportler = sportler
hans = Gesunder(2,3,3)
Note the the call to super(Gesunder, self).__init__ does not have self as the first argument.

In Python 2, super() on its own is invalid. Instead, you must use super(ClassName, self).
super(Gesunder, self).__init__(self, idn, artefakte)

The super() call should be modified to :
super(Gesunder, self).__init__(self, idn, artefakte)

Related

override a method of a class with an method from another class

I have following code:
class SomeClass:
def __init__(self) -> None:
pass
def some_class_function(self, par):
print(par)
class SomeOtherClass:
def __init__(self) -> None:
pass
def some_other_class_function(self, par):
print(par+1)
if __name__ == "__main__":
sc = SomeClass()
sc.some_class_function = SomeOtherClass.some_other_class_function
sc.some_class_function(1)
When I execute the code I get
TypeError: some_other_class_function() missing 1 required positional argument: 'par'
How can I override the method of the first class with the method of the second class properly?
As you have noted in the comments, you are interested in adding method that will use sc as the "self" instance.
To that end, see this post. To summarize, you can either add a function to the class definition (affecting future instances of the same class), or bind the function to the particular instance.
As an example, consider the following class and function.
class Test():
def __init__(self):
self.phrase = "hello world"
def func(self):
print("this is the old method")
def test_func(self):
print(self.phrase)
For the first approach, we could do the following
test = Test()
Test.func = test_func
test.func()
Note that future instances of Test will have this function as an attribute. For example, running Test().func() will still result in the same output, even though the method is being used on a new class instance.
For the second, we could do the following.
import types
test = Test()
test.func = types.MethodType(test_func, test)
test.func()
In this case, running the line Test().func() will result in the output "this is the old method" because func has not been overwritten for new instances.
You need to initialize the class to call its method.
sc = SomeClass()
sco = SomeOtherClass() # initialize the second call to call it's method
sc.some_class_function = sco.some_other_class_function
sc.some_class_function(1)

Python: can I generically combine base class and derived class [duplicate]

Say I have 2 different implementations of a class
class ParentA:
def initialize(self):
pass
def some_event(self):
pass
def order(self, value):
# handle order in some way for Parent A
class ParentB:
def initialize(self):
pass
def some_event(self):
pass
def order(self, value):
# handle order in another for Parent B
How can I dynamically let some 3rd class inherit from either ParentA or ParentB based on something like this?
class MyCode:
def initialize(self):
self.initial_value = 1
def some_event(self):
# handle event
order(self.initial_value)
# let MyCode inherit from ParentA and run
run(my_code, ParentA)
Simply store the class-object in a variable (in the example below, it is named base), and use the variable in the base-class-spec of your class statement.
def get_my_code(base):
class MyCode(base):
def initialize(self):
...
return MyCode
my_code = get_my_code(ParentA)
Also, you can use type builtin. As callable, it takes arguments: name, bases, dct (in its simplest form).
def initialize(self):
self.initial_value = 1
def some_event(self):
# handle event
order(self.initial_value)
subclass_body_dict = {
"initialize": initialize,
"some_event": some_event
}
base_class = ParentA # or ParentB, as you wish
MyCode = type("MyCode", (base_class, ), subclass_body_dict)
This is more explicit than snx2 solution, but still - I like his way better.
PS. of course, you dont have to store base_class, nor subclass_body_dict, you can build those values in type() call like:
MyCode = type("MyCode", (ParentA, ), {
"initialize": initialize,
"some_event": some_event
})
Just as a quick copy-and-paste-ready snippet, I've added the comments from shx2's answer to create this (memoized with a created_classes dict attribute, so that the classes created by successive identical calls with the same class will give identical classes):
class ParentA:
val = "ParentA"
class ParentB:
val = "ParentB"
class DynamicClassCreator():
def __init__(self):
self.created_classes = {}
def __call__(self, *bases):
rep = ",".join([i.__name__ for i in bases])
if rep in self.created_classes:
return self.created_classes[rep]
class MyCode(*bases):
pass
self.created_classes[rep] = MyCode
return MyCode
creator = DynamicClassCreator()
instance1 = creator(ParentA, ParentB)()
print(instance1.val) #prints "ParentA"
instance2 = creator(ParentB, ParentA)()
print(instance2.val) #prints "ParentB"
If you wanted to get fancy you could even make DynamicClassCreator a Singleton: https://stackoverflow.com/a/7346105/5122790
As an alternative to Chris's answer implementing the memoisation suggestion for shx2's answer, I'd prefer to use a memoize decorator (the end result is still a class but it's clearer to me that the function is the interface), and also use setdefault to simplify adding to the memo dict, and do not convert the names to string but use the tuple bases itself as the key, simplifying the code to:
class Memoize:
def __init__(self, f):
self.f = f
self.memo = {}
def __call__(self, *args):
return self.memo.setdefault(args, self.f(*args))
class ParentA:
def initialize(self):
pass
class ParentB:
def initialize(self):
pass
#Memoize
def get_my_code(base):
class MyCode(base):
def initialize(self):
pass
return MyCode
a1 = get_my_code(ParentA)
a2 = get_my_code(ParentA)
b1 = get_my_code(ParentB)
print(a1 is a2) # True
print(a1 is b1) # False
(Not a good example as the code provided doesn't actually do anything other than overwrite the parent class's initialize method...)

Python - Help on genetic algorithm error

I've been trying to create a genetic algorithm in python but i either get:
<bound method Environment.bestsol of <__main__.Environment instance
at 0x10a5d4ab8>>
or it doesn't print. I've tried to rearrange the functions, and call the function directly, but it still does not output anything. I seem to be having trouble with something relating to the function bestsol().
import random
import sys
from operator import attrgetter
input = 1
target = 5.5
class Individual:
def __init__(self, constant):
self.fitness = getfitness()
self.constant = constant
def getconstant():
return self.constant
def getresult():
return self.constant * input
def getfitness():
return 10 - abs(target - self.getresult())
def mutate():
if(random.random() > .05):
self.constant + random.random()
def offspring(partner):
return Individual(((self.getconstant() + partner.getconstant())/2))
class Generation(list):
def __init__(self, gensize, fitsize, startinglist=[]):
self.extend(startinglist)
self.bredoff = []
self.gensize = gensize
self.fitsize = fitsize
self.make()
def make():
self = [Individual(random.randint(-10,10)) for x in xrange((self.gensize-len(self)))]
def getfittest():
return heapq.nlargest(self.fitsize,self,key=attrgetter('fitness'))
def getbredoffspring():
for i in self.getfittest():
bredoff.append(i.offspring(self.getfittest[random.randint(0,len(self.getfittest()))]))
return bredoff
class Environment():
def __init__(self, maxgens):
self.l = []
self.b = []
self.maxgens = maxgens
def create():
l = Generation(100,20)
for i in maxgens:
b = l.getbredoffspring()
l = Generation(100,20,b)
def bestsol():
print("e")
print max(l,key=attrgetter('fitness')).fitness()
def main():
sol = Environment(2)
print sol.bestsol
if __name__ == '__main__':
main()
With me being new to python i can't understand even after searching the internet as best i could. Any help will be appreciated.
bestsol is a class method, so when you call it you should use brackets: sol.bestsol() (otherwise, you're print the method object: <bound method Environment.bestsol ...).
Second, when you define a class-method you should declare self as an argument:
def bestsol(self): # <-- here
print("e")
print max(l,key=attrgetter('fitness')).fitness()
Third, when you declare a class that doesn't extend any other class - you should either declare that it inherits from object (old way):
class Environment(object):
or, no brackets at all (new way)
class Environment:
Forth, when you create a class member, say l (you really should use better names btw), whenever you want to use it you should use the self annotation: self.l. If you'll use l it will create a local variable inside the method - and that's probably not what you intended.
There are other problems with the code but I'll let you struggle with it a bit so you can learn :)

python classes getters and setters static method and class method

class Spam(object):
#a_string = 'candy'
def __init__(self, sold=0, cost=0):
self.sold = sold
self.cost = cost
#staticmethod
def total_cost():
return True
#classmethod
def items_sold(cls, how_many):
#property
def silly_walk(self):
return print (self.a_string)
#silly_walk.setter
def silly_walk(self, new_string):
self.a_string = new_string.upper()
def do_cost(self):
if self.total_cost():
print('Total cost is:', self.cost)
.
from spam import Spam
def main ():
cost = 25
sold = 100
a_string = 'sweets'
sp = Spam(100, 25)
sp.do_cost()
sw = Spam.silly_walk(a_string)
sw.silly_walk()
if __name__ == '__main__':
main()
so im new to python and i don't understand how to use the setters and getters in this. so what i want to do is:
use #property to create a setter and getter for a property named silly_walk. Have the setter upper case the silly_walk string.
Show example code that would access the static method.
Show example code that would use the silly_walk setter and getter.
im getting very confused with what "self" does in the class and im not sure if what im doing is correct
update:
problem was the #classmethod not having a return and indentation error, so everything is fixed thanks everybody
self is convention. Since you're inside a class, you don't have functions there you have methods. Methods expect a reference to the object calling them as the first argument, which by convention is named self. You can call it anything you like.
class Foo(object):
def __init__(itsa_me_maaaario, name):
itsa_me_maaario.name = "Mario"
That works just as well.
As for the rest of your code -- what's your QUESTION there? Looks like your setter is a bit weird, but other than that it should work mostly okay. This is better:
class Spam(object): # inherit from object in py2 for new-style classes
def __init__(self, a_string, sold=0, cost=0) # put the positional arg first
...
#staticmethod
def total_cost():
# you have to do something meaningful here. A static method can't access
# any of the objects attributes, it's really only included for grouping
# related functions to their classes.
#classmethod
def items_sold(cls, how_many):
# the first argument to a classmethod is the class, not the object, so
# by convention name it cls. Again this should be something relevant to
# the class not to the object.
#property
def silly_walk(self):
return self.a_string
# don't call itself.
#silly_walk.setter
def silly_walk(self, new_string):
self.a_string = new_string
# it really just hides the attribute.
For instance I have a class I built to abstract a computer system I'm in charge of. It might be something like:
class System(object):
type_ = "Base system"
def __init__(self, sitenum, devicenum, IP):
self._sitenum = sitenum
self._devicenum = devicenum
self._IP = IP
# the leading underscores are a flag to future coders that these are
# "private" variables. Nothing stopping someone from using it anyway,
# because System()._IP is still that attribute, but it makes it clear
# that they're not supposed to be used that way.
#staticmethod
def ping_system(IP):
subprocess.call(["ping",IP], shell=True) # OH GOD SECURITY FLAW HERE
# group this with Systems because maybe that's how I want it? It's an
# aesthetic choice. Note that this pings ANY system and requires an
# argument of an IP address!
#classmethod
def type_of_system(cls):
return cls.type_
# imagine I had a bunch of objects that inherited from System, each w/
# a different type_, but they all inherit this....
#property
def description(self):
return "Site {}, Device {} # {}".format(self._sitenum,
self._devicenum,
self._IP)
#description.setter
def description(self, *args):
if len(args) == 3:
self._sitenum, self._devicenum, self._IP = args
elif len(args) == 1 and len(args[0]) == 3:
self._sitenum, self._devicenum, self._IP = args[0]
else:
raise ValueError("Redefine description as Sitenum, Devicenum, IP")
Example:
computer = System(1, 1, '192.168.100.101')
System.ping_system('192.160.100.101') # works
computer.type_of_system # "Base system"
computer.description # "Site 1, Device 1 # 192.168.100.101"
new_description = [1, 2, '192.168.100.102']
computer.description = new_description
# invokes description.setter
computer._devicenum # is 2 after the setter does its magic.

How to access a class method from a property definition

I have a model where I want to use a class method to set the default of for a property:
class Organisation(db.Model):
name=db.StringProperty()
code=db.StringProperty(default=generate_code())
#classmethod
def generate_code(cls):
import random
codeChars='ABCDEF0123456789'
while True: # Make sure code is unique
code=random.choice(codeChars)+random.choice(codeChars)+\
random.choice(codeChars)+random.choice(codeChars)
if not cls.all().filter('code = ',code).get(keys_only=True):
return code
But I get a NameError:
NameError: name 'generate_code' is not defined
How can I access generate_code()?
As I said in a comment, I would use a classmethod to act as a factory and always create you entity through there. It keeps things simpler and no nasty hooks to get the behaviour you want.
Here is a quick example.
class Organisation(db.Model):
name=db.StringProperty()
code=db.StringProperty()
#classmethod
def generate_code(cls):
import random
codeChars='ABCDEF0123456789'
while True: # Make sure code is unique
code=random.choice(codeChars)+random.choice(codeChars)+\
random.choice(codeChars)+random.choice(codeChars)
if not cls.all().filter('code = ',code).get(keys_only=True):
return code
#classmethod
def make_organisation(cls,*args,**kwargs):
new_org = cls(*args,**kwargs)
new_org.code = cls.generate_code()
return new_org
import random
class Test(object):
def __new__(cls):
cls.my_attr = cls.get_code()
return super(Test, cls).__new__(cls)
#classmethod
def get_code(cls):
return random.randrange(10)
t = Test()
print t.my_attr
You need specify the class name: Organisation.generate_code()

Categories