python def Method should have "self" as first argument - python

I’m studying python through the paid online course and i got an error by typing following codes while studying module and pakages.
class Fibonacci:
def __init__(self, title="fibonacci"):
self.title = title
def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()
def fib2(n):
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a + b
return result
and the def shows an error like "def Method should have "self" as first argument".
do you know why am i having an error? i think my code should be okay, and when i try to run it though my friends laptop(window) it works well btw, I’m using mac os.
sorry I’m just new to python .. :) click to see the error here
----- edited -----------------
thanks for the comments! and i have edited like the pictureedited code and it has no error! :)
but when i try to call the function, has an error like TypeError: fib() missing 1 required positional argument: 'n'
from pkg.fibonacci import Fibonacci
Fibonacci.fib(100)
see the error message
error message2

This is because all the functions within a class must have an argument named self if you want to bind the function to the class.
self represents the instance of the class. By using the self keyword we can access the attributes and methods of the class in python. It binds the attributes with the given arguments
Try This
class Fibonacci:
def __init__(self, title="fibonacci"):
self.title = title
def fib(self,n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()
def fib2(self,n):
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a + b
return result
Refer Self in Python Class
Edit:
Answering your other question
An object should be used while calling the class functions. So you have to define an object before you call the function.
Like this
from pkg.fibonacci import Fibonacci
f = Fibonacci()
f.fib(100)

Not sure if the fib / fib2 is the class method.
if they are, you may add self in the object parameter, as
def fib(self, n)
Then you may call the method like:
f = Fibonacci()
f.fib(5)
The self parameter is referring to the class object, so that you may use self attributes in the class method, in you case, you may have
def fib(self, n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()
print(self.title)

That's more likely a warning rather than an error.
And the warning is saying that you're declaring a method as a part of the class but it's not really bound to any object(missing self). If you're doing that on purpose, that means you ought to use static methods.
So you could either go ahead and add self to both those functions like has been suggested in the other answer, or you could use static methods
class Fibonacci:
def __init__(self, title="fibonacci"):
self.title = title
#staticmethod
def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()
#staticmethod
def fib2(n):
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a + b
return result
And the way you'd call it would be Fibonacci.fib(your_num_here)

Related

Use method within class to define a global variable

class Foo:
def add(self, a, b):
return (a+b)
def sub(self, a, b):
return (a-b)
C = add(1,2)
TypeError: add() missing 1 required positional argument: 'b'
How can I use a method within that class? When using a method within the class it is defined in, what should I pass in for the 'self' parameter?
I'm not too sure what you're getting at. The summary and description don't seem to match. I'll try to answer both to the best of my ability though.
GLOBAL_VAR = int()
class Foo:
def add(self, a, b):
return (a+b)
#staticmethod
def sub(a, b):
return (a - b)
def call_add(self, *args):
global GLOBAL_VAR
GLOBAL_VAR = self.add(*args)
C = Foo().add(1, 2)
D = Foo.sub(1, 2)
Foo().call_add(1, 2)
print(GLOBAL_VAR, C, D)
So the explanation.
If you want to update a global variable in a class method you have to bring it into the method with the it with the global keyword
if you want to access a class method you have to instantiate the class in the C = Foo().method() example
if you just want to call the method directly you can remove self and make it a static method in the D = Foo.sub() example.
if you want to call add in the class you need to call self.add
Hope that helps!

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

decorators and parameters check inside a python class

A class:
class Spam:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
An instantiation:
from Spam import *
c = Spam(1,5,4)
In this case, to perform a check on the input values of 'a' or 'b' or 'c' I've the decorators #property, #a.setter, #b.setter, #c.setter but...what if I need to check this variables but they are not directly copied into 'private' class variables?
I mean
class Egg()
def __init__(self, a, b, c):
self.var = (a + b)*c
Say I need to check a < c and c > b, what is the best way to perform checks on variables 'a', 'b', 'c' inside the class Egg and bound their value to some standards if checks are not consistent? Is there any particular decorator? (I need to keep code "clean and easy to uderstand" outside the class...this is why I am not performing checks before instantiation).
Have you considered immutability?
from collections import namedtuple
class Egg(namedtuple('Egg', 'a b c'))
def __new__(cls, a, b, c):
assert a < c and c > b
return super(Egg, cls).__new__(a, b, c)
#property
def var(self):
return (a + b)*c

How to use static/helper method in a class?

I'm writting a Fraction class and I am trying to use gcd(a,b) in the initialization of a Fraction object. However, when I was trying to do this it would not work WITHOUT the Fraction part of Fraction.gcd(a,b). I used #staticmethod here, but it does absolutely nothing, i.e. my code works the same without it.
Is there anyway I can call gcd without putting Fraction. in front of it? In Java I would normally create a static method and then just call it. I could very easily put the GCD code inside of the init, but I am trying to learn here!
I am missing a lot here. Can anyone explain: static methods, helper methods in a class and pretty much how I can use various methods inside of a class?
class Fraction(object):
def __init__(self, a, b):
if Fraction.gcd(a, b) > 1:
d = Fraction.gcd(a, b)
self.num = a/d
self.denom = b/d
else:
self.num = a
self.denom = b
#staticmethod
def gcd(a,b):
if a > b: a,b = b,a
while True:
if b % a == 0: return a
a, b = b%a, a
def __repr__(self):
return str(self.num) + "/" + str(self.denom)
Don't forget, in Python not everything needs to be in a class. There's nothing about gcd that makes it better-suited to being a class method than a standalone function: so take it out of the class. Now you can just call gcd(a, b).
Think of methods in a class just like any other class attribute -- reference them on self:
def __init__(self, a, b):
if( self.gcd(a,b) > 1):
d = self.gcd(a,b)
It doesn't matter whether it's an instance method, class method, or static method.
While you certainly can use a staticmethod if you want to keep the code associated with the class, it's usual in Python to use a module-level function, in which case you can call it as gcd:
def gcd(a,b):
if a > b: a,b = b,a
while True:
if b % a == 0: return a
a, b = b%a, a
class Fraction(object):
def __init__(self, a, b):
if( gcd(a,b) > 1):
d = gcd(a,b)
If you have a big method within your class that requires many calls to a static method you can define a local function object and assign the method to it so you can call this function instead.
For Static Method gdc:
class Fraction(object):
def __init__(self, a, b):
gcd = Fraction.gcd
if( gcd(a,b) > 1):
d = gcd(a,b)
self.num = a/d
self.denom = b/d
else:
self.num = a
self.denom = b
#staticmethod
def gcd(a,b):
if a > b: a,b = b,a
while True:
if b % a == 0: return a
a, b = b%a, a
def __repr__(self):
return str(self.num) + "/" + str(self.denom)
For Instance Method gdc:
class Fraction(object):
def __init__(self, a, b):
gcd = self.gcd
if( gcd(a,b) > 1):
d = gcd(a,b)
self.num = a/d
self.denom = b/d
else:
self.num = a
self.denom = b
def gcd(self,a,b):
if a > b: a,b = b,a
while True:
if b % a == 0: return a
a, b = b%a, a
def __repr__(self):
return str(self.num) + "/" + str(self.denom)
So
gcd = Fraction.gcd
and
gcd = self.gcd
will allow you to call (without Fraction at the beginning as per your request :))
gcd(a,b)
Also, if you want some basic examples of python classes and instance/static methods
have a look at some of my blog posts, specially the one called "Factorial and Fibonacci in Jython":
http://carlosqt.blogspot.com/search/label/Jython
I think you are referring to Java's "import static" feature.
Just to clarify: as Java enforces object orientation, it cannot have "modules" like other languages. So using import static Math.*; for example will make all static methods on Math available to be called without the class name.
In Python you can just add this function outside a class and call it.
That's how static methods work. You call them via Classname.methodname() (or via instance.methodname(), but self won't be available inside the method).
What you want is a regular function on the module level. Define it outside the class and do not decorate it.

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