returning instances in python - python

class classname():
def func(self,a,b):
self.c = a+b
self.d = a-b
self.e = a*b
return self
cn = classname()
This way i can access cn.c, cn.d and cn.e can i use something else other then self to return it and it will be a structure. I know its possible in matlab where you can define structure in a function. Something what i expect should look like this:
class classname():
def func(self,newself,a,b):
self.c = a+b
self.d = a-b
newself.e = a*b
return self, newself
cn = classname()
I know this is not a valid code but just an idea what i want from code.

I think what you want is this:
class classname:
def __init__(self, a, b):
self.c = a+b
self.d = a-b
self.e = a*b
cn = classname(12, 34) # Just random values for 'a' and 'b'. Use whatever you like!
print(cn.c)
>>> 46
print(cn.d)
>>> -22
print(cn.e)
>>> 408
The __init__ function is automatically called when the object is created. Self will always refer to the object, so adding attributes to it will add it to the object, so you don't need to return anything.

Related

Is there any way to automatically create a constructor for python?

I have a class C like the following, and I can't construct it like C("a", 1, 2.5).
class C(object):
def __init__(self):
self.A = ""
self.B = 0
self.C = 1.2
So I write the following function make_c.
def make_c(a, b, c):
c = C()
c.A = a
c.B = b
c.C = c
However, this is not neat, and I have to create differenct versions of make_CLS for every CLS. So I am wondering if there are some ways that I do not need to write make_c.
Maybe the following code works, but I don't know if it is the best way, since exec is needed, and I still have to name all fields.
def make_common(cls_name, fields_map):
o = eval(cls_name)
for k,v in fields_map.iteritems():
exec "o.{}={}".format(k, v)
return o
This question is under Python2, however, if there are better ways only in Python3, I am also willing to know that.
--EDIT--
I can not alter definition of class C, because there codes are all generated by some other programs.
Maybe something like this? this avoids using eval
def make_class(cls_name, fields):
my_class = globals()[cls_name]()
my_class.__dict__.update(fields)
return my_class
Then
my_class = make_class('C', {'a':1, 'b':2, 'c':3})
Why not just add the variables you want to pass to your __init__() function?
class C(object):
def __init__(self,a , b, c):
self.A = a
self.B = b
self.C = c
test = C("a", 1, 2.5)
test.A
#'a'

Passing arguments self into function

How can I pass in arguments (a, b, c) to a function for a quadratic formula without having to redefine them in the function? I know I could use self.a instead of just a inside the formula (same thing for b and c) but how do I pass in the argument self.a as a, self.b as b, and self.c into the function?
class Calc:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def quadraticformula(self):
c = self.c
b = self.b
a = self.a
neg = ((b*-1)-(sqrt((b**2)-4*a*c)))/(2*a)
pos = ((b*-1)+(sqrt((b**2)-(4*a*c))))/(2*a)
return (pos,neg)
Instead of using a class with a constructor function just use a normal function in general
def calc(a, b, c):
neg = ((b*-1)-(sqrt(b**2 - 4*a*c)))/(2*a)
pos = ((b*-1)+(sqrt(b**2 - 4*a*c)))/(2*a)
return pos, neg
Then call the function:
>>> calc(1, 2, -3)
(1.0, -3.0)
You don't have to redefine anything. The __init__ method allows for all other methods of the class to be able to access that variable. So once you actually define a variable you passed to the class (you referenced it as a function, which its not) in the __init__ method all you have to do it just reference it with whatever operation you need.
# within you quadraticformula method
...
neg = ((self.b*-1)-(sqrt(self.b**2 - 4*self.a*self.c)))/(2*self.a)
pos = ((self.b*-1)+(sqrt(self.b**2 - 4*self.a*self.c)))/(2*self.a)
return pos, neg
When passing attributes to the class you have create an instance of it like so:
a = # something
b = # something
c = # something
cl = Calc(a, b, c)
cl.quadraticformula() # call the method (a function with a method) of the function here
# You can call this method in the __init__ method if you want to
# execute as soon as you call the class instead of using the instance
# to reference it
class Calc:
def __init__(self,a,b,c):
self.a = a
self.b = b
self.c = c
self.quadraticformula

Use default init values of other classes

I have 2 classes with some functions:
class A:
def __init__(self, one=1, two=2):
self.one = one
self.two = two
def do_smt(self):
...
class B:
def __init__(self, value="test"):
self.value = value
def do_smt(self):
...
I have a third class that has to use the 2 classes is doing this.
class C:
def __init__(self, one=1, two=2, value="test"):
self.A = A(one, two)
self.B = B(value)
def do_smt(self):
...
Now I do this: new_class = C()
But what if the default value of class A or B changes, then I also need to change that in class C. Is there a way to write class C in a way that it knows which arguments are the default ones? It need to handle no arguments but also arguments that other classes expect.
You can use inspect.signature to obtain the parameters of the __init__ method of each "base" class of class C, and let C.__init__ accept variable keyword arguments, so that it can iterate through the "base" classes and pass to the __init__ method of each just what it needs and what the given keyword arguments have. Use itertools.islice to ignore the first parameter, which is always self:
import inspect
from itertools import islice
class C:
bases = A, B
params = {}
for cls in bases:
params[cls] = inspect.signature(cls.__init__).parameters
def __init__(self, **kwargs):
for cls in self.bases:
setattr(self, cls.__name__, cls(**{key: kwargs[key] for key in
islice(self.params[cls], 1, None) if key in kwargs}))
so that:
c = C(one=3,value='hi')
print(c.A.one)
print(c.A.two)
print(c.B.value)
outputs:
3
2
hi
You could use some sentinel value (here None) and pass parameters only if they are provided as something meaningful:
class C:
def __init__(self, one=None, two=None, value=None):
if one is two is None:
self.A = A()
else:
self.A = A(one, two)
if value is None:
self.B = B()
else:
self.B = B(value)
That way, A and B's defaults take care of themselves.
One solution is to factor the default values to constants:
DEFAULT_ONE = 1
DEFAULT_TWO = 2
class A:
def __init__(self, one=DEFAULT_ONE, two=DEFAULT_TWO):
pass
Use the constants in class C as well.
Before the call class A and B, define init values to variables
Try add these before calls in class C init:
self.initA_one = A.one
self.initA_two = A.two
self.initB_value = B.value
And continue
self.A = A (.,.)
self.B = B (.)
EDIT:
this was what i meant.
class C():
def __init__(self, one=-1, two=-2, value="detest"):
self.initA_one = A().one
self.initA_two = A().two
self.initB = B().value
self.A = A(one, two)
self.B = B(value)
def do_smt(self):
print()
new_class = C()
print(f'default A.one is {new_class.initA_one}, new value A.one is {new_class.A.one}.')
print(f'default A.two is {new_class.initA_two}, new value A.two is {new_class.A.two}.')
print(f'default B.value is {new_class.initB}, new B.value is {new_class.B.value}')
gives
default A.one is 1, new value A.one is -1.
default A.two is 2, new value A.two is -2.
default B.value is test, new B.value is detest
I am not sure if this fits exactly what you want, but basically you can let C decide what to give to A, B and let A, B decide what to use, using **kwds method parameters in A and B.
One of the differences, with the sample class C2, is that, if C has a different default value it overrides A, B.
There is also another alternative, under C3, where you use a guard value (not using None to allow that to be a default) to only pass on arguments that were given to C3.
class A:
def __init__(self, one=1, two=2, **kwds):
self.one = one
self.two = two
def do_smt(self):
pass
class B:
def __init__(self, value="test", **kwds):
self.value = value
class C:
def __init__(self, one=1, two=2, value="test"):
self.A = A(one, two)
self.B = B(value)
class C2:
""" your default values override those of A, B"""
def __init__(self, one=1, two=2, value="test"):
locals_ = locals()
locals_.pop("self")
self.A = A(**locals_)
self.B = B(**locals_)
undefined = NotImplemented
class C3:
""" your default values dont affect A and Bs"""
def __init__(self, one=undefined, two=undefined, value="test"):
locals_ = {k:v for k,v in locals().items() if k != "self" and v is not undefined}
self.A = A(**locals_)
self.B = B(**locals_)
#can still use it locally
self.one = one if one is not undefined else 11
self.two = two if two is not undefined else 22
c= C()
print("c.A.one:", c.A.one)
print("c.B.value:", c.B.value)
c2= C2()
print("c2.A.one:", c2.A.one)
print("c2.B.value:", c2.B.value)
c3= C3()
print("c3.A.one:", c3.A.one)
print("c3.one:", c3.one)
print("c3.B.value:", c3.B.value)
output:
c.A.one: 1
c.B.value: test
c2.A.one: 1
c2.B.value: test
c3.A.one: 1
c3.one: 11
c3.B.value: test
You could even have a variant of C that uses **kwds itself and pass those on to A, B in case they find value in it.
class C4:
""" your default values dont affect A and Bs
and you can pass in anything.
Neither two or value are known to C and that's OK"""
def __init__(self, one=undefined, **kwds):
locals_ = locals()
locals_ = {k:v for k,v in locals().items() if k not in ("self","kwds") and v is not undefined}
locals_.update(**kwds)
self.A = A(**locals_)
self.B = B(**locals_)
#can still use it locally
self.one = one if one is not undefined else 11
c4= C4(value="somevalue")
print("c4.A.one:", c4.A.one)
print("c4.A.two:", c4.A.two)
print("c4.one:", c4.one)
print("c4.B.value:", c4.B.value)
output:
c4.A.one: 1
c4.A.two: 2
c4.one: 11
c4.B.value: somevalue
I think the best (and pythonic) way to write such classes is always using None as default for any optional argument in any class. In class A and B you then check whether the respective argument is None and if so, replace by your real default value. That way the default for each attribute is defined in only one place and class C doesn't need to know the default value.

Calling the same method in all the objects from a class

I'm quite new using Python and can't find the answer to this.
Let's souppose I have a code like:
class numbers():
def __init__(self,a,b):
self._a = a
self._b = b
def add(self):
self._suma = self._a + self._b
After that, I create a lot of instances of numbers:
obj1 = numbers(1,2)
obj2 = numbers(7,16)
...
Then, I want to call the add method in all the objects of the class numbers in a simple and clean way.
Notice that if I instantiated numbers class 1000 times I don't want to write 1000 times this
objX.add()
I looked for an answer in the web and I found that, in other lenguages, they put all the names of the objects in a string, and then iterates on it calling the method.
The problem is I donĀ“t know how to do that in python, nor if it's the best way to solve this problem.
Thank you
create a list of objects.
objs = []
add elements to this list
obj1 = numbers(1,2) # say these are your objects
obj2 = numbers(7,16)
...
objs.append(obj1) # add them to the list
call the add method for each element in the list
for obj in objs:
obj.add() # call the add method.
Well you'll need to have some way to find all the numbers objects. For clarity, I'll adjust your code naming conventions slightly so they're more standard (per PEP9).
class Number(object):
def __init__(self, a, b):
self._a = a
self._b = b
def add(self):
self.sum = self._a + self._b
return self.sum # not really sure where we're using it, so here?
a = Number(1, 2)
b = Number(2, 3)
c = Number(3, 4)
Now we have three objects, a, b, and c, that are all Number objects. There's two ways to get a list of them, and one is really bad. We'll go over that one first.
number_objs = [obj for obj in globals() if isinstance(obj, Number)]
for number in number_objs:
number.add()
This queries the all the objects currently in the namespace to see if they're Numbers. The problem with doing it this way is that you lose encapsulation. You probably don't want to rely on your functions finding a number object by calling globals(). Instead, let's give Number an encompassing object!
class NumberList(list):
# this is literally just a list, but we want to add one method:
def make_number(a, b):
number = Number(a, b)
self.append(number)
all_numbers = NumberList()
a = all_numbers.make_number(1, 2)
b = all_numbers.make_number(2, 3)
c = all_numbers.make_number(3, 4)
for number in all_numbers:
number.add()
Alternatively you can give Number a classmethod that works as an alternate constructor, but also adds it to a list. This is probably the cleanest way to handle it.
class Number(object):
def __init__(self, a, b):
self._a = a
self._b = b
def add(self):
self.sum = self._a + self._b
return self.sum
#classmethod
def track(cls, a, b, container):
n = cls(a, b)
container.append(n)
return n
all_numbers = []
a = Number.track(1, 2, all_numbers)
b = Number.track(2, 3, all_numbers)
c = Number.track(3, 4, all_numbers)
for number in all_numbers:
number.add()
You need to append each obj to a list. To automate that, simply create an empty list and write the code inside the init. This will run automatically every time a new object is created
class numbers():
def __init__(self,a,b):
self.a = a
self.b = b
listObjs.append(self)
def Add(self):
return self.a + self.b
listObjs = []
ob1 = numbers(4,5)
ob2 = numbers(4324,5)
ob3 = numbers(1,25)
ob4 = numbers(2,5324)
ob5 = numbers(21,5)
ob6 = numbers(4213,54)
Then simply make a loop and print the obj.Add(). This will run for each obj in the list.
for obj in listObjs:
print(obj.Add())
Output:
9
4329
26
5326
26
4267

Accessing a function within a function(nested function?) [duplicate]

This question already has answers here:
How to access a function inside a function?
(6 answers)
Closed 6 years ago.
Python noob here.
How do I get hold of the 'inner' function within the 'fib' function?
from time import sleep
class Fibonacci(object):
def __init__(self, a, b, limit=50):
self.a = a
self.b = b
self.limit = limit
def fib(self):
while self.a < self.limit:
c = self.a + self.b
sleep(1)
print self.a,
self.b = self.a
self.a = c
def inner(self):
print 'Damn it! Just print already!'
j = Fibonacci(0,1,2)
j.fib()
## This doesn't work. Gives an "AttibuteError: 'function' object has no attribute 'inner'"
j.fib.inner()
You cannot, not unless fib returns inner somehow. inner is essentially a local variable inside the scope of fib and you can't access a function's locals from outside of it. (That wouldn't even make sense, since the locals don't exist except when the function is running. Think about it -- would it make sense to access fib's c variable from outside of the function?)
Do not use the following.
[...]
>>> j = Fibonacci(0,1,2)
>>> j.fib()
0 1 1
>>> # dark magic begins!
>>> import new
>>> new.function(j.fib.im_func.func_code.co_consts[2],{})(None)
Damn it! Just print already!
You can tell simply by looking at it that it's not really Python, and for that matter it isn't really calling the "inner" function itself, it's simply creating a new function like it. I also didn't bother setting the globals 'correctly', because this is a terrible thing to do in the first place..
[I should mention that the point of the above is to note that the idea that you can't access internals from outside isn't strictly true, though it's almost never a good idea. Exceptions include interpreter-level code inspections, etc.]
Unclean! Unclean!
from time import sleep
class Fibonacci(object):
def __init__(self, a, b, limit=50):
self.a = a
self.b = b
self.limit = limit
def fib(self):
while self.a < self.limit:
c = self.a + self.b
sleep(1)
print self.a,
self.b = self.a
self.a = c
def inner(self):
print 'Damn it! Just print already!'
Fibonacci.fib.inner = inner
fib.inner = None
This code snippet will allow you to use inner.
The below seems to achieve what you want
from types import CodeType, FunctionType
def find_nested_func(parent, child_name):
""" Return the function named <child_name> that is defined inside
a <parent> function
Returns None if nonexistent
"""
consts = parent.func_code.co_consts
for item in consts:
if isinstance(item, CodeType) and item.co_name==child_name:
return FunctionType(item, globals())
As stated by some of the other readers, it's a problem of scope. FWIW, this works by returning the inner function:
from time import sleep
class Fibonacci(object):
def __init__(self, a, b, limit=50):
self.a = a
self.b = b
self.limit = limit
def fib(self):
while self.a < self.limit:
c = self.a + self.b
sleep(1)
print self.a,
self.b = self.a
self.a = c
def inner():
print 'Damn it! Just print already!'
return inner
j = Fibonacci(0,1,2)
j.fib()()
For reference, here's a good intro to python's scoping:
Short Description of the Scoping Rules?

Categories

Resources