How to run a class function - python

I was trying to write some code that would take in the number of sides of a polygon and a user can just randomly input the length of each side
I wanted to make a separate class polygon and the following was my code:
#numSides=int(input(Number of sides))
class polygon(object):
def __init__(self,x): #useless code
self.x=x #useless code
self.x=[] #useless code
def __inputSides__(self):
#counter=0
#for i in range(x):
# counter=counter+1
numSides=int(input("number of sides"))
list_=[]
for i in range(numSides):
length=float(input("length"))
list_.append(length)
return list_
def __dispSides__(self,list_):
for i in list_:
print("side length",i)
stone= polygon()
stone.__dispSides__(4)
but then in the second to last line i was getting an error that said :
Traceback (most recent call last):
File "python", line 23, in <module>
TypeError: __init__() missing 1 required positional argument: 'x'
I was wondering how can i fix this and why I am getting this error?
thanks!

A proper class wouldn't prompt the user for the side lengths; the code that creates a Polygon should be responsible for the I/O and simply pass the values as arguments to Polygon.__init__.
class Polygon(object):
def __init__(self, sides):
self.sides = sides
def display_sides(self):
for s in self.sides:
print("side length", s)
numSides = int(input("number of sides"))
sides = []
for i in range(numSides):
length = float(input("length"))
sides.append(length)
s = Polygon(sides)
s.display_sides()

This is a quite straight-forward question.
Whenever you call your polygon class its __init__ function is run automatically. You've set this initiation function to require 2 arguments: self & x. Whenever you initiate your class you will thus have to provide your class with an x argument.
Meaning instead of declaring stone = polygon(), you should declare something like stone = polygon(x).
Furthermore, your reason for passing and initiating the x argument is unclear since no matter what value x is given, it is never passed along to any method within your class. This is because after declaring self.x = x, it is immediately overwritten to be an empty list by your self.x=[] declaration (leaving the actual x-argument unused).

In same code, I applied two fixes.Hope you wanted the same result.
class polygon(object):
def __init__(self,x=[]): #useless code
self.x=x
# force user to input numSide and length
numSides=int(input("number of sides"))
list_=[]
for i in range(numSides):
length=float(input("length"))
list_.append(length)
#finally list_ argument is a declaration so you have to define it(assign value)
def __dispSides__(self,list_=list_):
for i in list_:
print("side length",i)
stone= polygon()
stone.__dispSides__()
fix 1: __init__(self,x=[]): define x with declaration to set a default value
fix 2:
def __dispSides__(self,list_=list_):
here you declared a variabe list_ but actually you wanted to pass previous list_ value here(as it seems ) so do pass it a value.
Avoid Error: stone.__dispSides__(4)# passing a non-iterable will raise an error

Related

python class attributes as standard input in a class method

I don't seam to be able to do this but is would make sense that you could.
So mybe I just made a mistake.
class Foobar:
def __init__(self):
self.myatr = 0
def add(self, someinput=self.myatr): # <-- someinput=self.myatr???
return someinput += 1
but you get the error
NameError: name 'self' is not defined
But it would be logicl if the this was the way it worket
f = Foobar()
f.add() # returns 1
f.add(1) # returns 2
Instance methods are functions bound to class attributes, defined when the class is defined, before any instance exists. Similarly, the default value is set once, at definition time, not on-demand when the method is called without an explicit argument.
As such, you need a sentinel (typically None) which signals that no argument was passed.
def add(self, someinput=None):
if someinput is None:
someinput = self.myatr
return someinput + 1
Default arguments are evaluated at function definition. Moreover, the names of the arguments defined earlier (like self in your function) aren't available during function definition. So when you refer to self.myattr, there's no self yet.
For example, consider this function:
>>> def test(thing=print('hello')):
... ...
...
hello
>>>
The expression print('hello') was evaluated right when the function was defined, and it won't be re-evaluated when you call test.
Also, return someinput += 1 is an error too because assignment is not an expression.
Furthermore, integers are always copied, so if you do this:
def test(x):
x += 1
return x
a = 6
test(a)
a will still be equal to six, since the call test(a) copied a.

Error while defining the class

I'm new to "class" in python. I created a following class in python. The objective of this class is, if pass a list of numbers, if the sum of 2 numbers is 50, it will return me the position of those number in the list.
from itertools import combinations
class numList(object):
def findComb(self):
a = []
b = []
for comb in combinations(self, 2):
a.append(comb)
for i in range(1, len(a)):
if sum(a[i]) == 50:
b.append(a[i])
return b
c = numList()
c.findComb([10,20,10,40,50,60,70])
But I'm getting the following error, when I'm trying to execute it:
TypeError: findComb() takes 1 positional argument but 2 were given
Please let me know where I'm making the mistake.
Thank you!
By design, the first argument of every class function is always a reference to the current instance of the class (always named self).
You are calling findComb with an additional argument when you defined it to only take one (self).
def findComb(self):
...
should be
def findComb(self, myList):
...
All your references to self in your function implementation will need to be updated accordingly to use myList.
Each method within a class takes as positional input the instance of the class itself, unless you add the #staticmethod decorator.
So you are receiving the error because the function findComb receives as input:
the instance (by default)
the list you passed
This should clarify the error you are receiving.
You can fix it in two ways:
Assigning the input list to an attribute of the class and then use the attribute in the function:
class numList(object):
def __init__(self, inp_list):
self.input = inp_list
def findComb(self):
a = []
b = []
for comb in combinations(self.input, 2):
a.append(comb)
for i in range(1, len(a)):
if sum(a[i]) == 50:
b.append(a[i])
return b
c = numList([10,20,10,40,50,60,70])
c.findComb()
Define findComb as a staticmethod, so that it would only use the argument you are passing (without using the instance as first argument):
class numList(object):
#staticmethod
def findComb(inp_list):
a = []
b = []
for comb in combinations(inp_list, 2):
a.append(comb)
for i in range(1, len(a)):
if sum(a[i]) == 50:
b.append(a[i])
return b
c = numList()
c.findComb([10,20,10,40,50,60,70])

python TypeError: 'int' object is not callable

i have homework and we need to do something like iterator, the func work great but the techer told he run the func with (t=Make_iterator()) like this, what i do wrong? tnx!
global x
x=-1
def Make_iterator(fn):
global x
x+=1
return fn(x)
fn=lambda y:y*2
t=Make_iterator(fn)
print(t())
I think you want a closure, which is a function defined within the local namespace of anther function, so that it can access the outer function's variables:
def make_iterator(func):
x = -1
def helper():
nonlocal x
x += 1
return func(x)
return helper
The nonlocal statement allows the inner function to modify the variable declared in the outer function (otherwise you'd either get an error, or you'd bind your own local variable without changing the outer one). It was only added in Python 3, so if you're still using Python 2, you'll need to wrap the x value in a mutable data structure, like a list.
Another approach to the same idea is to write class, rather than a function. An instance of a class can be callable (just like a function) if the class defines a __call__ method:
class MyIterator(object):
def __init__(self, func):
self.index = -1
self.func = func
def __call__(self):
self.index += 1
return self.func(self.index)
This can be useful if the state you need to keep track of is more complicated (or should change in more complicated ways) than the simple integer index used in this example. It also works in Python 2 without annoying workarounds.
I think he wants your Make_iterator function to return a function that acts as an iterator. So you could wrap the contents of your current Make_iterator function within an inner function f and return that:
def Make_iterator(fn):
def f():
global x
x+=1
return fn(x)
return f
Now if you do t = Make_iterator(fn), every time you call t() it will return the next value of the iterator, in your case 0, 2, 4, 6, 8, etc...

Wrong number of arguments when a calling function from class in Python

I'm trying to write an implementation of a genetic algorithm in python. It says there I am calling it with two arguments when only one is allowed, but I'm sure I'm not.
Here is the relevant code:
class GA:
def __init__(self, best, pops=100, mchance=.07, ps=-1):
import random as r
self.pop = [[] for _ in range(pops)]
if ps == -1:
ps = len(best)
for x in range(len(self.pop)): #Creates array of random characters
for a in range(ps):
self.pop[x].append(str(unichr(r.randint(65,122))))
def mutate(array):
if r.random() <= mchance:
if r.randint(0,1) == 0:
self.pop[r.randint(0, pops)][r.randint(0, ps)] +=1
else:
self.pop[r.randint(0, pops)][r.randint(0, ps)] -=1
This is the code when I initialize and call from the class:
a = GA("Hello",10,5)
a.mutate(a.pop)
which returns the following error from IDLE:
TypeError: mutate() takes exactly 1 argument (2 given)
How can I fix this?
Methods of a class are automatically passed the instance of the class as their first argument (it's named self by convention):
def mutate(self, array):

TypeError: takes exactly 2 arguments (1 given)

class DLLNode(object):
def __init__(self, data, prev_link, next_link):
self.data = data
self.prev_link = prev_link
self.next_link = next_link
class DoublyLinkedList(object):
def __init__(self):
self.head=None
self.tail=None
def add_head(self, add_obj):
self.head=DLLNode(add_obj,None,self.head)
>>> x=DoublyLinkedList
>>> x.add_head(1)
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
x.add_head(1)
TypeError: add_head() takes exactly 2 arguments (1 given)
Guessing x isn't counting as an argument because it's not getting instantiated right.
x = DoublyLinkedList()
not
x = DoublyLinkedList
not including parens assigns the DoublyLinkedList module object to x, it doesn't create a new one.
When you write
x = DoublyLinkedList
you assign the class DoublyLinkedList to x, not an instance of it. add_head being an instance method, it cannot be called on the class directly. Instead, you need to use
x = DoublyLinkedList()
x.add_head(1)
This way, python will be able to substitute self with x, and you will have 2 arguments to your call.
You need to create an instance of the object when assigning to x
x = DoublyLinkedList()
The former syntax (DoubleLinkedList) is allowed because classes are valid as objects.

Categories