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.
Related
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.
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
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)
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.
So I am in an intro to python class and we are just getting into class basses coding in python. I am looking to get a list of areas out of the plants in my list so that I can then take those areas, get a sum, and then subtract them from the area in the bed. I am having the trouble figuring out how to make a list of the area of the plants in my bed, which is only blueberries for now. Any ideas are greatly appreciated.
class crop:
name = "Crop"
sizeW = 0
sizeL = 0
areaOfCrop=sizeL * sizeW
def print(self):
print("This is a ",self.name," and is ",self.sizeW,"X",self.sizeL, "and has an area of ",self.areaOfCrop)
def willItFit(self, W, L):
return self.sizeW <= W and self.sizeL <= L
def sameAs(self, crop):
return self.name == crop.name
class plant(crop):
name = "Plant"
sizeW = 1
sizeL = 1
areaOfCrop = sizeL * sizeW
class parsley(plant):
name = "Parsley"
class shrub(crop):
name = "Shrub"
sizeW = 2
sizeL = 2
areaOfCrop = sizeL * sizeW
class blueberries(shrub):
name = "Blueberries"
class tree(crop):
name = "tree"
sizeW = 3
sizeL = 3
areaOfCrop = sizeL * sizeW
class dwarfPeach(tree):
name = "Dwarf Peach"
class bed:
sizeL = int(input("What is the length? "))
sizeW = int(input("What is the width? "))
crops = [blueberries()] # The list of crops in this bed
areaOfAllCrops = [crops[areaOfCrop()]] #this is where my problem is
def print(self):
print("The bed is ", self.sizeL," x ", self.sizeW)
for c in self.crops:
c.print()
def maxSizeAvailable(self):
''' area of bed-total area of all crops in be '''
return (self.sizeW, self.sizeL)
def add(self, newCrop):
dimension = self.maxSizeAvailable()
if newCrop.willItFit(dimension[0], dimension[1]):
self.crops.append(newCrop)
def remove(self, existingCrop):
for c in self.crops:
if c.sameAs(existingCrop):
self.crops.remove(c)
def checkFit(self, crop):
dimension = self.maxSizeAvailable()
return crop.willItFit(dimension[0], dimension[1])
b = bed()
b.print()
You can add up the areas of the crop instances in the crops list with sum(x.areaOfCrop for x in crops). This is a generator expression that gets passed to the builtin function sum.
But I think you have a larger conceptual issue that will cause you problems later on even you get your immediate issue squared away. The issue is that you're exclusively using class attributes in your code, rather than instance attributes. While there are some situations where class attributes are useful, the overwhelming majority of the time you want to be dealing with instance attributes instead.
To create instance attributes, you need to make the assignments in a method, and assign to self.attr instead of just attr. Usually the place to initialize your instance attributes is the __init__ method, which Python will call for you after it creates the new instance.
To give an example, your crop class should probably start with:
class crop:
def __init__(self):
self.name = "Crop"
self.sizeW = 0
self.sizeL = 0
self.areaOfCrop = sizeL * size
# ...
Some of those values could be passed as arguments, rather than always getting set to the same constant. That leads me to a design question: Do you need all of your different plants to be instances of separate classes, or could they all be different instances of one class, with different data in their instance attributes attributes? (Don't be too concerned if you don't know the answer yet. It takes some experience with OOP to get good at designing classes.)