check if inner functions were created by the same function - python

lets supose that i have something like:
def a(b):
def c(d):
# do someting
# ...
# ...
return something_else
return c
and then this:
q = a(54)
w = a(97)
e = a(12)
is there any way to know if for example q and w where both created by a ? or is there anything that i can make to check it ?
i though about doing an empty class and then inheit from that one overwriting __call__ and using issubclass but it seems a little bit hacky (and will raise if its actually a normal function), and maybe there is a better option.
thanks.

You could duck punch it:
def a(b):
def c(d):
# do stuff
return stuff
c.created_by = 'a'
return c
So then when you use it...
q = a(54)
w = a(97)
q.created_by == w.created_by # True
Not judging since I don't know why you're trying to do this, or really understand the problem, but personally I think this is a bigger hack than doing it via classes:
class A(object):
def __init__(self, b):
self.b = b
class C(A):
def do_stuff(self, d):
return self.b * d
q = C(54)
w = C(97)
isinstance(q, A) # True

Related

Polymorphism and Overriding in Python

I have two classes: A and B. I would like to build a class C which is able to overrides some common methods of A and B.
The methods which I would like to override they should be able to call the method of the base class.
In practice I would like to collect some statistics about class A and B, but being transparent to the rest of my code. Now, A and B have some methods in common (obviously implemented in a different way). I would like to have a class C which shares the interface of A and B, and simoultaneously do some other operations (i.e. measure the run time of some shared methods).
I can make this example:
import time
class A:
def __init__(self):
pass
def common_method(self):
return "A"
class B:
def __init__(self):
pass
def common_method(self):
return "B"
class C:
def __init__(self, my_obj):
self.my_obj
self.time_avg = 0
self.alpha = 0.1
pass
def common_method(self):
start = time.time()
ret = self.my_obj.common_method()
stop = time.time()
self.time_avg = (1. - self.alpha) * self.time_avg + self.alpha * (stop - start)
return ret
I hope that from this example is clear that A and B inheriting from C is not working.
However, this method unfortunately require me to redefine all the methods of classes A and B... Which is tedious and dirty!
What is the proper way to implement this situation in python? And how it is called the design pattern (I am almost sure that there is but I cannot recall).
Thanks in advance.
You could solve this with composition instead of polymorphism, meaning that a C object will hold either a A object or a B one:
class C:
def __init__(self, obj):
self._obj = obj
def common_method(self):
return self._obj.common_method()
You can then use it:
>>> ca = C(A())
>>> cb = C(B())
>>> ca.common_method()
'A'
>>> cb.common_method()
'B'
Beware: if you pass an object that does not declare a common_method method, you will get an AttributeError

Python 3: Using OOP to change Class to Integer on Conditional Statement

Apologies for incorrect lingo, I am still new to this.
I want to make a class initialiser that, using a conditional, will decide whether or not the instance of said class will collapse into a simple integer.
Simplified Unworking Example:
class A(object):
def __init__(self,a,b):
self.a = a
self.b = b
if self.b == 0:
return int(a)
def __repr__(self):
return str(a)+":"+str(b)
DoesntBecomeAnInt = A(3,4)
WillBecomeAnInt = A(3,0)
print(DoesntBecomeAnInt,WillBecomeAnInt)
##Desired Output:
##3:4, 3
Any help would be very much appreciated!
You should use the magic method __new__ for this. __new__ is used as a factory where you can decide which class should be instantiated.
class A(object):
def __new__(self, a):
return int(a)
A(4)
> 4
A(4).__class__
> <type 'int'>
class A:
def __new__(cls, a, b):
if b == 0:
return a
return super().__new__(cls)
def __init__(self, a, b):
print('Initilizing')
self.a = a
self.b = b
def __repr__(self):
return str(self.a)+":"+str(self.b)
__new__ is the method used to control the creation of new objects (hence the name). Here we check if b is zero in __new__ and return an instance of the appropriate type.
In action:
>>> DoesntBecomeAnInt = A(3,4)
Initilizing
>>> WillBecomeAnInt = A(3,0)
>>> print(DoesntBecomeAnInt,WillBecomeAnInt)
3:4 3
You don't.
The behavior you desire is completely unexpected and somewhat bizarre. Calling A() is expected to return an instance of A. Doing anything else is confusing and unintuitive, which makes it difficult to read and understand any code invoking it.
Alternative
If you really need this behavior, create a factory method:
def make_thing(a, b):
if 0 == b:
return int(a)
else:
return A(a, b)
Obviously, you need a better name than make_thing, but without any context, I can't give you any suggestions.
Avoid the problem if possible
Since A is not a number and is generally not compatible with int, it is also somewhat strange to store both int and A in the same variable.
If all you're doing is converting to a string, then you don't need a class at all. A simple method outside of a class is the better alternative:
def a_and_b_to_string(a, b):
if b == 0:
return str(int(a))
else:
return str(a) + ":" + str(b)
If you're doing more than that, your calling code will probably end up looking something like this:
x = make_thing(input1, input2)
if isinstance(x, A):
result = x.some_method_from_a() # Or some other calculation requiring an A
else:
result = 5 * x # Or some other calculation requiring an `int`
This is somewhat silly: you write a method to choose the data type and then have to write specialized code for each possible result. You're not getting any benefits from having a function that returns the separate types here. I can think of two simpler alternatives:
Just move the check to the calling code:
if input2 == 0:
temp = A(input1, input2)
result = temp.some_method_from_a() # Or some other calculation requiring an A
else:
result = 5 * int(input1) # Or some other calculation requiring an int
If you go this route, you should also modify A.__init__ to throw a ValueError if b == 0, since that would be an invalid state for an A to be in.
Modify A so that it works properly regardless of whether b is 0:
class A(object):
def __init__(self,a,b):
self.a = a
self.b = b
def some_method_from_a():
if self.b == 0:
# Some calculation involving only a
return int(self.a) * 5
else:
# Some other more complex calculation involving both a and b
return self.a * self.b * 6
def __repr__(self):
if self.b == 0:
return str(int(self.a))
else:
return str(self.a) + ":" + str(self.b)
Then
x = A(a, b)
result = x.some_method_from_a()
But again, it's hard to provide recommendations without knowing how you're actually using it.
Using dataclasses
# A(...) should either raise an exception or
# return an instance of A to avoid confusion.
# create can do whatever you want it to.
import dataclasses
#dataclasses.dataclass
class A:
print('Initializing')
a : int
b : int
def __repr__(self):
if self.b == 0:
return str(int(self.a))
else:
return str(self.a) + ":" + str(self.b)
#classmethod
def create(cls, a, b):
if b == 0:
return a
return cls(a, b)
DoesntBecomeAnInt = A.create(3,4)
WillBecomeAnInt = A.create(3,0)
print(f'{DoesntBecomeAnInt}\n{WillBecomeAnInt}')
Initializing
3:4
3
[Program finished]

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

How can i let class methods interact with a context manager in python?

My code contains some objects which are used via Pythons "with" statement to ensure that they get savely closed.
Now i want to create a class where the methods can interact with these objects.
For example my code actually looks like this:
with ... as a, with ... as b:
# do something with a and b here
call_method(a, b) # pass a and b here
I'd like to put it into a class, so it Looks "like" this:
class Something(object):
def __init__(self):
with ... as a:
self.a = a
with ... as b:
self.b = b
def do_something(self):
# do something with self.a and self.b
self.call_method(self.a, self.b)
def call_method(self, a, b)
# do more with a, b
The objects need to stay "opened" all the time.
I don't know how to achieve this, so how can i do this?
You don't have a 'context' in your class to manage, don't use with in __init__. You'll have to close the files in some other manner.
You can always use try:, finally: if you want the file objects to be closed if there is an exception within the method:
def call_method(self, a, b)
try:
# do more with a, b
finally:
self.a.close()
self.b.close()
but it depends heavily on what you wanted to do with the files if you really wanted them to be closed at that point.
If your instances themselves should be used in a specific context (e.g. there is a block of code than starts and ends during which your instance should have the file open), then you can make the class a context manager by implementing the context manager special methods.
You alone as designer of the class API will know how long the files need to stay open for. It depends heavily on how the instance is used when it is time to close the file.
You could make your class itself a context manager:
class Something(object):
def __init__(self):
self.a = a
self.b = b
def __enter__(self):
self.a_e = a.__enter__(self)
self.b_e = b.__enter__(self)
def __exit__(self, *x):
xb = False
try:
xb = self.b_e(*x)
finally:
xa = self.a_e(*x)
return xa or xb # make sure both are called.
def do_something(self):
# do something with self.a and self.b
# - or, if present, with a_e, b_e
self.call_method(self.a, self.b)
def call_method(self, a, b)
# do more with a, b
This is just the raw idea. In order to make it work properly, you must do even more with try: except: finally:.
You can use it then with
with Something(x, y) as sth:
sth.do_something()
and it gets properly __enter__()ed and __exit__()ed.

Python List of different class' objects

Hello I have declared a class in Python and then I want to make a list of objects of this class and print it. I am new to python and I cannot figure out what I am doing wrong. I know C++ and this is what I would like to do
class Word:
def __init__(self,word,hor):
self.word=word
self.x1=0
self.y1=0
self.x2=0
self.y2=0
self.hor=hor
def get_dimensions(self):
return(self.x1,self.y1,self.x2,self.y2)
def set_dimensions(self,t):
self.x1=t[0]
self.y1=t[1]
self.x2=t[2]
self.y2=t[3]
def get_horizontal():
return self.hor
def display(self):
print word
def WordList(word_list,hor):
l=[]
for x in word_list:
w1=Word(x,hor)
l.append(w1)
return l
li=["123","23","43"]
li=WordList(li,True)
for x in li:
x.display #obviously something else has to be done here
Also I get the following compilation problem when I try to run it:
[<__main__.Word instance at 0x7ffc9320aa70>, <__main__.Word instance at 0x7ffc9320ab00>, <__main__.Word instance at 0x7ffc9320ab48>]
Can you help me?
You are attempting to print the method itself, rather than call it.
Use the following instead:
for x in li:
x.display()
You can also provide a custom str method;
class SomeClassHere(object):
def __init__(self, a):
self.a = a
def __str__(self):
return "Hello %s" % ( self.a, )
>>> a = SomeClassHere(a="world")
>>> print a
Hello world
To answer your additional question on whether the types match or not;
>>> class Hello(object):
... def __init__(self, a):
... self.a = a
...
>>> b = Hello(a=1)
>>> c = Hello(a=2)
>>> d = Hello(a=3)
>>> b == c
False
>>> c == d
False
>>> isinstance(b, Hello)
True
You can change this behaviour by modifying __eq__ and __cmp__ - see:
How is __eq__ handled in Python and in what order?
You need to fix two bugs:
def display(self):
print self.word #Added self here
and
for x in li:
x.display() #Added brackets here

Categories