Not sure what is wrong with the Python code below. Will appreciate any help. I have looked into here and here, but could not solve my issue.
Code:
class myClass:
def factorial(n,self):
if n == 1:
return 1
else:
return n * self.factorial(n-1)
obj = myClass()
obj.factorial(3)
Error
Traceback (most recent call last):
File "a.py", line 9, in <module>
obj.factorial(3)
File "a.py", line 6, in factorial
return n * self.factorial(n-1)
AttributeError: 'int' object has no attribute 'factorial'
You transposed the parameter names for factorial. The one that refers to the object itself must come first. As it is, you're trying to access the factorial variable of the number that was passed in. Change your definition of factorial to this:
def factorial(self, n):
...
self needs to be the first argument to a class function. Change
def factorial(n,self)
to
def factorial(self, n)
change your method signature to
def factorial(self, n)
instead of
def factorial(n, self)
because when you call a class method via object. python expects reference to the class object as a first parameter. in your case it's 'int'. which is not reference to the class object.
Related
I'm new to Python, and am trying to figure out if there is a way to specify the variable type in a parameter definition. For example:
def function(int(integer))
as opposed to:
def function(integer)
int(integer)
I know it's not a major difference, but I'm trying to use good programming practices here, and if I'm defining a function with a large number of parameters, it could get messy.
As of Python 3.4 you can add type annotations to a function or method:
def function(a: int):
pass
However these types are not enforced - you can still call the function with a value that is not an integer.
Furthermore, Python is based on the idea of duck typing so you may sometimes want to accept a variety of types, such as both int and float for a particular function.
Python uses Duck typing which means you should not discriminate objects based on what type they are, but based on what attributes and functions they have. This has many advantages which are outside of the scope of this answer.
What you should do instead if you want to add documentation to your function is to use a docstring
def square(x):
"""takes a number and squares it"""
return x**2
and type hints
def square(x: int) -> int:
"""takes a number and squares it"""
return x**2
if you really need to check the arguments given to you, you can do a hasattr() to check for the attributes and functions the argument provides. In most situations (including this one) just not checking the type is better
def square(x):
"""takes a number and squares it"""
if not hasattr(x, "__pow__"):
raise TypeError("unsupported operand:", type(x))
return x**2
If you want to use the syntax
def function(a: int):
pass
mentioned by #SimeonVisser and you have python3.5, you can use the decorator I wrote
from typing import get_type_hints
def strict_types(f):
def type_checker(*args, **kwargs):
hints = get_type_hints(f)
all_args = kwargs.copy()
all_args.update(dict(zip(f.__code__.co_varnames, args)))
for key in all_args:
if key in hints:
if type(all_args[key]) != hints[key]:
raise Exception('Type of {} is {} and not {}'.format(key, type(all_args[key]), hints[key]))
return f(*args, **kwargs)
return type_checker
while defining functions like that
#strict_types
def concatenate_with_spam(text: str) -> str:
return text + 'spam'
and it will raise an exception if the argument passed to your function is of the wrong type.
Traceback (most recent call last):
File "strict_types.py", line 23, in <module>
concatenate_with_spam(1)
File "strict_types.py", line 13, in type_checker
raise Exception('Type of {} is {} and not {}'.format(key, type(all_args[key]), hints[key]))
Exception: Type of text is <class 'int'> and not <class 'str'>
Though I haven't implemented a way to check the type of what you return and this solution won't suit you if you want to check it too.
>>> def function(integer :int):
assert isinstance(integer, int), 'your error message'
print(integer * integer)
>>> function(3)
9
>>> function('3')
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
function('3')
File "<pyshell#5>", line 2, in function
assert isinstance(integer, int), 'your error message'
AssertionError: your error message
I'm trying to make a Taylor series in Python and I don't know how to remove this error:
x=Symbol("x")
def f(x):
return ((math.e)**x)*sin(x)
y=f(x)
print(y.diff(x))
def Taylor(f,x,m,a):
y=f(x)
y2=f
yargliige=0
viga = 10**(-m)
n=0
while True:
if n>10:
return yargliige,n
else:
yargliige+=(y(x)*(x-a)**n)/(factorial(n))
y=y.diff(x)
if abs(yargliige(x)-f(x))<viga:
return yargliige,n
n+=1
print(Taylor(f,-0.3,3,-1))
Error message I get:
Traceback (most recent call last):
File "C:\Users\arman\Desktop\Numbrilised meetodid\praktikum10.py", line 31, in <module>
print(Taylor(f,-0.3,3,-1))
File "C:\Users\arman\Desktop\Numbrilised meetodid\praktikum10.py", line 25, in Taylor
yargliige+=(y(x)*(x-a)**n)/(factorial(n))
TypeError: 'Float' object is not callable
It seems that the original function doesn't accept float, which seems ridiculous.
You've already called y = f(x) which stores the returned float from the function f.
You can not do y() as y is not callable.
Change y = f(x) to y = f and it should solve your use case.
I see that you are trying to call yargliige as a function yargliige(x) which is not applicable since it's a variable not function.
If I define the __iter__ method as follows, it won't work:
class A:
def __init__(self):
self.__iter__ = lambda: iter('text')
for i in A().__iter__():
print(i)
iter(A())
Result:
t
e
x
t
Traceback (most recent call last):
File "...\mytest.py", line 10, in <module>
iter(A())
TypeError: 'A' object is not iterable
As you can see, calling A().__iter__() works, but A() is not iterable.
However if I define __iter__ for the class, then it will work:
class A:
def __init__(self):
self.__class__.__iter__ = staticmethod(lambda: iter('text'))
# or:
# self.__class__.__iter__ = lambda s: iter('text')
for i in A():
print(i)
iter(A())
# will print:
# t
# e
# x
# t
Does anyone know why python has been designed like this? i.e. why __iter__ as instance variable does not work? Don't you find it unintuitive?
It is done by design. You can find the thorough description here: https://docs.python.org/3/reference/datamodel.html#special-method-lookup
Short answer: the special method must be set on the class object itself in order to be consistently invoked by the interpreter.
Long answer: the idea behind this is to speed up well-known constructions. In your example:
class A:
def __init__(self):
self.__iter__ = lambda: iter('text')
How often are you going to write a code like this in real life? So, what Python does - it skips a dictionary lookup of the instance, i.e. iter(A()) simply does not "see" that self.__iter__, which is actually self.__dict__['__iter__'] in this case.
It also skips all the __getattribute__ instance and metaclass lookup gaining a significant speedup.
Basically, I'm trying to code the Gauss Elimination(Foward) method, but, when executed, Python raises an exception saying: "Object has no attribute '__getitem__'" when the subtraction between 2 lists occurs.
The complete stacktrace is:
Traceback (most recent call last):
File line 35, in <module>
b=a.GaussForward()
File line 29, in GaussForward
self.a[index][w]=self.a[index][w]-aux[i][w]
TypeError: 'float' object has no attribute 'getitem'
I'll post the code below.
class TestGauss():
a=[]
def __init__(self,A):
self.a=A
def __getitem__(self,i):
return self.a[i]
def __setitem__(self,i,value):
self.a[i]=value
def GaussForward(self):
pivo=0.0
fact=0.0
aux=[]
for i in range(len(self.a)):
pivo=self.a[i][i]
for j in range(i+1,len(self.a[0])):
fact=self.a[j][i]/float(pivo)
print fact
for k in range(len(self.a[0])):
self.a[i][k]*=fact
for w in range(len(self.a[0])):
aux=self.a[i]
if i+1<len(self.a[0]):
index=i+1
self.a[index][w]=self.a[index][w]-aux[i][w]
print self.a
Your problem lies with aux[i][w]. Since you set aux=self.a[i], aux is a flat list (ie. not a list of lists) and thus when you try to access aux[i][w], you're trying to index self.a[i][i][w] which is not correct. I think you meant to do this:
self.a[index][w]=self.a[index][w]-aux[w]
I am newbie in python so it may sound a stupid question.
Scenario:
I have a cluster class, while creating its instance i am supplying it with two default value which are nothing but coordinates for the centroid which will be of ty
from checkbox.lib.text import split
class point:
x=0
y=0
def toString(self):
return (self.x+ ':'+self.y)
def __init__(self,a,b):
self.x=a
self.y=b
class cluster:
points=[]
centroid= point
def __init__(self,a,b):
centroid= point(a,b)
def kMeans(lis,k):
length=len(lis)
clusters=[]
for i in range(k):
clusters.append(cluster(2*i,2*i))
print clusters[i].centroid.toString()
for pt in lis:
min=10
centroidNum=0
for i in range(k):
dist=(abs(int(pt.x)- int(clusters[i].centroid.x))) +abs((int(pt.y) - int(clusters[i].centroid.y)))
if dist<min:
min=dist
centroidNum=i
clusters[centroidNum].points.append(pt)
for cl in clusters:
print "Clusters"
for pt in cl.points:
print pt.toString()
def readValues():
try:
fileHandler = open('/home/sean/input/k_means.txt', 'r')
for line in fileHandler:
tokens=split(line,",")
if len(tokens) == 2:
tempObj=point(tokens[0].strip(),tokens[1].strip())
list.append(tempObj)
except IOError:
print "File doesn't exist"
if __name__ == '__main__':
list=[]
readValues();
kMeans(list,3)
I am tring to assign value to centroid thus passing in constructor. But i am getting below error:
unbound method toString() must be called with point instance as first argument (got nothing instead)
I want the centroid to be a point so that i can access in rest of the program.
Please help me how to assign value to centroid
input file has points in form
1,2
3,5
4,3
You are not giving us the full code for your problem.
Couple of general Python syntax issues first:
Class names should be CamelCase (class Point and class Cluster)
Function names should be lower case (to_string(self): )
You've also got some random semicolons around there from Java(script) syntax I'm guessing.
It looks like the line
centroid = Point
is creating an unbound instance of Point (should be centroid = Point() but you'd also need to pass 2 arguments as a and b).
Try removing this line so the Point() instance is created in the __init__ function of Cluster.
Edit 1:
Here's your problem;
In your __init__ of Cluster you are setting a variable centroid but not applying it to the instance (self). As a result, it is trying to use centroid = Point you are setting within the instance, which is unbound.
Try this setup:
class cluster:
points=[]
def __init__(self,a,b):
self.centroid = point(a,b)
I've got rid of the unnecessary (and wrong) initialisation of centroid= point and am now setting centroid as an attribute to the class in the __init__ method.
The error
unbound method toString() must be called with point instance as first
argument
usually occurs when you call an instance method of class on the class directly and instead of an instance of the object.
Example:
class foo(object):
def bar(self):
print 'bar'
print foo.bar()
Traceback (most recent call last):
File "out", line 6, in <module>
print foo.bar()
TypeError: unbound method bar() must be called with foo instance as first argument (got nothing instead)
So you have to call
foo().bar()