Variable declaration as a member of a function? - python-3.x

What type of declaration is the one indicated in this code
def call_counter(func):
def helper(x):
helper.calls1 += 1 # <== This
return func(x)
helper.calls1 = 0
return helper
#call_counter
def succ(x):
return x + 1
print(succ.calls1)
for i in range(10):
print(succ(i))
print(succ.calls1())
What's the name of this is the first time i see something like this

Functions are just objects in Python, so the same way you can add new attributes to instances of your own classes (and to the classes themselves) you can add them to your functions:
def foo():
pass
class Bar:
pass
bar = Bar()
foo.spam = 1
bar.spam = 2
print(foo.spam) # 1
print(bar.spam) # 2
Generally one wouldn't add new attributes to a function object though, since it can quickly get messy and hard to keep track of.

Related

What is the purpose of constructor in Python?

Do constructors initialize attributes for a specific object at the time of object creation?
I created a simple class for addition.
I used constructor and initialized two parameters a and b.
Now I created an add method in that class. For which I used same letters a and b.
Now when I create an object, like
Object = class(a-value, b-value)
Print(object.add())
I was expecting that initialized a and b values to be sent to add method.
But error is still asking me to pass the positional arguments for add()
And when I print(object.a) - I get the initialized value for a!
So is constructor used for passing attributes for that specific object?
While add function needs parameters and arguments for those parameters?
Full Code(from comment):
class Addition:
def __init__(self, a, b):
self.a = a
self.b = b
def addition(self, a, b):
add=a+b
return add
object1 = Addition(20, 30)
print(object1.addition())
You're including local arguments when you don't need to.
Simply removing them and referring to the instance variables(attributes) will fix your problem.
class Addition:
def __init__(self, a, b):
self.a = a
self.b = b
def addition(self):
add = self.a + self.b
return add
object1 = Addition(20, 30)
print(object1.addition())
Python is very helpful when you create an object and implicitly passes the instance as the first argument to a bound method.
For this reason, we need to always include an argument in our methods that the instance can be handed to.
The standard name for this argument is self (although it can be anything) it is helpful to readers of your code to refer it to as everyone else does.
So calling object1.addition() is essentially doing this on a normal unbound function.
def normal_func_addition(some_object):
add = some_object.a + some_object.b
return add
object1 = Addition(20, 30)
print(normal_func_addition(object1))
Your other question was "Why need a constructor at all?"
The answer to this is it's a good place to set our attributes on the object.
Again, we could achieve this with a simple top level function.
def func_init(some_object, a, b):
some_object.a = a
some_object.b = b
class Addition:
pass
object1 = Addition()
func_init(object1, 20, 30)
print(object1.a)
print(object1.b)
or even directly.
object1.a = 20
object1.b = 30
But that's a lot of boilerplate and it's nice to do it all in one step.
So in essence, object1 = Addition(20, 30) creates an Addition object (object1) and hands that object to __init__ along with 20 and 30.
There you assign the attributes .a and .b to it. Then when you call object1.addition() it again hands the instance (object1) to it. There you can pull the attributes back out that you assigned in __init__.
Is this helpful?
class Test():
def __init__(self, a, b):
self.a = a
self.b = b
def add(self):
return self.a + self.b
test = Test(15, 10)
print(test.a)
print(test.b)
print(test.add())

Is there a way to pass all variable to a function in python

I have part of a function I would like to turn into another function. I want this new function to be able to edit the variables in in the parent function. Is this possible in python.
I know in other languages that a class can inherent their parents variables and function. I am wondering if there is something similar to this in python?
check here for scoping then here and here for closures. You are ideally looking for enclosing functions. The variables defined within the enclosing functions are available to the sub-functions as though they were globally defined. Most of these are widely dealt with in other languages.
def m(x,y):
z = 2
j = 4
def n():
return x+y+z+j
return n()
m(3,1)
10
is that what you are looking for !
class Parent:
# two class variables x,y
x = 100
y = 100
def __init__(self):
pass
def sum_from_parent(self):
return self.x+self.y
class Child(Parent):
def __init__(self):
super().__init__() # init super class to create x,y variables
def sum_child(self):
# edit base class variables
x_in_child = Parent.x+20
y_in_child = Parent.y+20
return(x_in_child+y_in_child)
c = Child()
print("sum in parent = ", c.sum_from_parent())
print("sum in child = ", c.sum_child())
answer will be
sum in parent = 200
sum in child = 240

How to refer to an attribute of a first object, which creates with a method a second object?

I'm currently trying to build a simple animation for a queuing model and I want to set the coords of any graphical object in dependence of its predecessor object. To do so, I call a method of the object (o1), which I want to animate. This method creates an object (o2) of another class, which represents the image. While creating o2, I want to pass an attribute of o1. This looks, for instance, like this:
class Queue(salabim.Queue):
def setup(self, predecessor):
self.predecessor = predecessor
def animate(self, graphic):
self.graphic = graphic
buffer_preprocessing = Queue(
name = 'buffer_preprocessing',
predecessor = source)
if env.animation is True:
buffer_preprocessing.animate(graphic = Symbol_Queue(
width = 80,
height = ref_height,
slots = 5,
x = predecessor.graphic.x + predecessor.graphic.width + distance,
y = y0,
fillcolor = 'white'))
When compiling the program, I receive an error "[pylint] Undefined variable 'predecessor' [undefined-variable]".
Can somebody tell me, which keyword I need to use to refer to the attributes of the outside object "buffer_preprocessing"?
Thanks in advance :-)
Edit: It is possible to simplify my problem to the following code:
class OuterClass():
def __init__(self, A):
self.A = A
def do_stuff(self, stuff):
self.stuff = stuff
class InnerClass():
def __init_(self, B):
self.B = B
outerclass = OuterClass(A=1)
outerclass.do_stuff(stuff = InnerClass(B = 1 + A))
# Error: Undefined variable 'A'
# How can I refer to the calling object 'outerclass' without giving the explicit name?
I am guessing both the Queue and the Symbol_Queue since neither the name nor the predecessor parameters are part of python's queue.Queue.
If this is so, I believe the change needs to be implemented inside the code of the Queue class... maybe something along the lines:
First, expose the predecessor inside the Queue
class Queue(...):
def __init__(self, name, predecessor, ...):
...
# expose the predecessor
self.predecessor = predecessor
or alternatively, if you need to do some processing/checking you can expose a property
class Queue(...):
def __init__(self, name, predecessor, ...):
...
# expose the predecessor
self._predecessor = predecessor
#property
def predecessor(self):
# .. some checks or processing
return self._predecessor
Second, your code above will now become something like:
buffer_preprocessing = Queue(
name = 'buffer_preprocessing',
predecessor = source)
if env.animation is True:
buffer_preprocessing.animate(graphic = Symbol_Queue(
width = 80,
height = ref_height,
slots = 5,
x = buffer_preprocessing.predecessor.graphic.x + buffer_preprocessing.predecessor.graphic.width + distance,
y = y0,
fillcolor = 'white'))
There probably might be better ways to pass this by changing a little the implementation of the .animate, but it's hard to say without looking at the implementation of the Queue and Symbol_Queue classes.
EDIT 1: Using the simpler abstraction added to the question
I believe the key here would be to include some kind of logic inside the OuterClass.do_stuff, since in there you can access the things within self. Of course, it depends how much you can "hardcode" into this function on the OuterClass.
Here is a suggestion (I define the Inner first for better readability):
class InnerClass():
def __init_(self, B):
self.B = B
class OuterClass():
def __init__(self, A):
self.A = A
def do_stuff(self, stuff_to_create_inner):
new_inner = InnerClass(B = 1 + self.A, **stuff_to_create_inner)
# You can use "**" (dict unpacking), or pass them "by hand"
# ...
self.stuff = stuff
outerclass = OuterClass(A=1)
outerclass.do_stuff() # in your example you may want to pass the width, height, ...
Finally, should you need to use/keep track of that inner object you created (I'm guessing you don't since you simply create on inside the method call), you could always have OuterClass.do_stuff return the created object.
Thanks for the simplification. Now it’s much clearer. In that case, you can simply pass the class as well as the argument to do_stuff rather than creating an object when calling the do_stuff function. For example,
class OuterClass():
def __init__(self, A):
self.A = A
def do_stuff(self, my_class, other_input):
self.obj = my_class(other_input+self.A)
class InnerClass():
def __init_(self, B):
self.B = B
outerclass = OuterClass(A=1)
outerclass.do_stuff(my_class = InnerClass, other_input=1)

OOP - Call function containing instance of class within the same class

I am new to programming and have done some research on instance, class, and static variables. Lately, I have tried to simplify my code on my projects to help me learn more in Python. In this particular instance, no pun intended, I'd like to be able to call the somefoo() function that will assign arguments to the init instance variables one and two, depending on conditions. From my understanding, in order to call the somefoo() function, the Foo() class must be instantiated; however, the parameters the class requires are within the somefoo() function within that class. Thank you in advance!
import random
class Foo():
def __init__(self, one, two):
self.foobar = random.random()
self.one = one
self.two = two
def somefoo(self):
if self.foobar > 0.5:
one = ':)'
two = 1
Foo(one, two)
if self.foobar < 0.5:
one = ':('
two = 0
Foo(one, two)
somefoo()
To begin with, I don't even know if you have checked your code before posting it here for help because there is something really wrong with it. There are lot of syntax mistakes. This is how it's supposed to be...
import random
class Foo:
def __init__(self, one, two):
self.foobar = random.random()
self.one = one
self.two = two
def somefoo(self):
if self.foobar > 0.5:
one = ':)'
two = 1
Foo(one, two)
if self.foobar < 0.5:
one = ':('
two = 0
Foo(one, two)
somefoo()
There were parenthesis before the class name which were not required in python along with useless indents. Python is sensitive when it comes to indents so make sure your indents are meaningful, and use them logically. Now coming to your question; here is how it can be done:
import random
class Foo:
def __init__(self, one, two):
self.foobar = random.random()
self.one = one
self.two = two
self.somefoo()
def somefoo(self):
if self.foobar > 0.5:
self.one = ':)'
self.two = 1
if self.foobar < 0.5:
self.one = ':('
self.two = 0
def __str__(self):
return str(self.one)+" "+str(self.two)
print(Foo(10,20))
Basically the part where you are trying to call somefoo is not wrong and yes python does execute the class down to the bottom when it makes a object of it in memory, but in your code the method is of bound type (i.e. it needs and object for execution). So what you can do is use some sort of object factory pattern, or go with the one I have pasted above, in which as soon as object is generated, it calls the bound method which swipes the data of instance in question and displays the output. In python3 unbound methods are introduced which can be used without the self object reference. Make sure you look into them too and how they work, as they may help you to come with more flexible solution to your problems.

increase the size of array deque

I'm trying to be as efficient as possible with space while creating an array based deque. So, the array starts with size one, and I'll call a function called "grow" if the array is not large enough when I push new values to the deque (at either end). I then mod to preserve the front and back of the deque. Here is a sample of what I've done so far:
def __init__(self):
# capacity starts at 1; we will grow on demand.
self.__capacity = 1
self.__contents = [None] * self.__capacity
self.__front = 1
self.__back = 1
self.__size = 1
def __grow(self):
old_list = self.__contents
walk = self.__front
for k in range(self.__capacity):
self.__contents[k] = old_list[walk]
walk = (1 + walk) % len(old_list)
self.__front = 0
self.__capacity = self.__capacity * 2
def push_front(self, val):
if self.__size == len(self.__contents):
self.__grow(self.__capacity)
self.__front = (self.__front - 1) % len(self.__contents)
self.__contents[self.__front] = val
self.__size += 1
My question comes when I call the grow method. I keep getting the error that I am giving 'grow' two positional arguments, but I don't see where or how that's happening. If anyone has any ideas on how to improve this so that it only has one positional argument? Also, does my reasoning for a walk through to re-index in the grow method make sense as well as my reasoning for the push front method?
You need to add an argument to __grow if you are going to pass arguments to it, i.e.:
def __grow(self, size):
Currently, it only has a self argument, but you are also passing in self.__capacity when you call it. However, I think you really meant to call grow without arguments:
if self.__size == len(self.__contents):
self.__grow()
All instance methods in a class treat the calling instance as their first argument, unless you use the class to call the method in which case you must provide an instance as the first argument.
class A:
def __init__(self):
pass
def f(self, x):
print(self, x)
a = A()
a.f(1) # <A object at 0x7fa9a067da90> 1
A.f(a, 2) # <A object at 0x7fa9a067da90> 2
So when you call self.__grow(self.__capacity), that gets turned into Deque.__grow(self, self.__capacity). But your __grow method only takes self.

Resources