How to change an instance variable in python using a method? - python

I'm very new to python and currently practicing OOP. One of the problems I'm facing is how to change an instance variable in python using a method.
My code:
class Monster:
def __init__ (self, name, health):
self.name = name
self.health = health
#classmethod
def change_name (self, given_name):
self.name = given_name
mon = Monster("Drake", 100)
print(mon.name)
mon.change_name("Derrick")
print(mon.name)
Output:
#Expected:
Drake
Derrick
#Actual:
Drake
Drake
Can someone tell me what the problem is and how I can solve it?

It happens because the change_name method is declared as a
classmethod
Which means its self parameter is not the object (instance of the class) but the class, in fact you should rename it to cls to make it clear.
Assigning tbe variable via the class creates it in the class' namespace, not in the object's.
But when looked up via the object, python looks for it in the object's namespace and if it cannot be found, it looks for it in the class' (and above in the superclasses' if not found yet)
Since you do not seem to need it , as the name attribute belongs to each monster instance, the solution is to make the method a plain instance one by removing the #classmethod decorator.

Related

Attribute error when opening a window with buttons. 'DataInput' object has no attribute 'graph' [duplicate]

Consider this example:
class MyClass:
def func(self, name):
self.name = name
I know that self refers to the specific instance of MyClass. But why must func explicitly include self as a parameter? Why do we need to use self in the method's code? Some other languages make this implicit, or use special syntax instead.
For a language-agnostic consideration of the design decision, see What is the advantage of having this/self pointer mandatory explicit?.
To close debugging questions where OP omitted a self parameter for a method and got a TypeError, use TypeError: method() takes 1 positional argument but 2 were given instead. If OP omitted self. in the body of the method and got a NameError, consider How can I call a function within a class?.
The reason you need to use self. is because Python does not use special syntax to refer to instance attributes. Python decided to do methods in a way that makes the instance to which the method belongs be passed automatically, but not received automatically: the first parameter of methods is the instance the method is called on. That makes methods entirely the same as functions, and leaves the actual name to use up to you (although self is the convention, and people will generally frown at you when you use something else.) self is not special to the code, it's just another object.
Python could have done something else to distinguish normal names from attributes -- special syntax like Ruby has, or requiring declarations like C++ and Java do, or perhaps something yet more different -- but it didn't. Python's all for making things explicit, making it obvious what's what, and although it doesn't do it entirely everywhere, it does do it for instance attributes. That's why assigning to an instance attribute needs to know what instance to assign to, and that's why it needs self..
Let's say you have a class ClassA which contains a method methodA defined as:
def methodA(self, arg1, arg2):
# do something
and objectA is an instance of this class.
Now when objectA.methodA(arg1, arg2) is called, python internally converts it for you as:
ClassA.methodA(objectA, arg1, arg2)
The self variable refers to the object itself.
Let’s take a simple vector class:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
We want to have a method which calculates the length. What would it look like if we wanted to define it inside the class?
def length(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
What should it look like when we were to define it as a global method/function?
def length_global(vector):
return math.sqrt(vector.x ** 2 + vector.y ** 2)
So the whole structure stays the same. How can me make use of this? If we assume for a moment that we hadn’t written a length method for our Vector class, we could do this:
Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0
This works because the first parameter of length_global, can be re-used as the self parameter in length_new. This would not be possible without an explicit self.
Another way of understanding the need for the explicit self is to see where Python adds some syntactical sugar. When you keep in mind, that basically, a call like
v_instance.length()
is internally transformed to
Vector.length(v_instance)
it is easy to see where the self fits in. You don't actually write instance methods in Python; what you write is class methods which must take an instance as a first parameter. And therefore, you’ll have to place the instance parameter somewhere explicitly.
When objects are instantiated, the object itself is passed into the self parameter.
Because of this, the object’s data is bound to the object. Below is an example of how you might like to visualize what each object’s data might look. Notice how ‘self’ is replaced with the objects name. I'm not saying this example diagram below is wholly accurate but it hopefully with serve a purpose in visualizing the use of self.
The Object is passed into the self parameter so that the object can keep hold of its own data.
Although this may not be wholly accurate, think of the process of instantiating an object like this: When an object is made it uses the class as a template for its own data and methods. Without passing it's own name into the self parameter, the attributes and methods in the class would remain as a general template and would not be referenced to (belong to) the object. So by passing the object's name into the self parameter it means that if 100 objects are instantiated from the one class, they can all keep track of their own data and methods.
See the illustration below:
I like this example:
class A:
foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]
class A:
def __init__(self):
self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []
I will demonstrate with code that does not use classes:
def state_init(state):
state['field'] = 'init'
def state_add(state, x):
state['field'] += x
def state_mult(state, x):
state['field'] *= x
def state_getField(state):
return state['field']
myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)
print( state_getField(myself) )
#--> 'initaddedinitadded'
Classes are just a way to avoid passing in this "state" thing all the time (and other nice things like initializing, class composition, the rarely-needed metaclasses, and supporting custom methods to override operators).
Now let's demonstrate the above code using the built-in python class machinery, to show how it's basically the same thing.
class State(object):
def __init__(self):
self.field = 'init'
def add(self, x):
self.field += x
def mult(self, x):
self.field *= x
s = State()
s.add('added') # self is implicitly passed in
s.mult(2) # self is implicitly passed in
print( s.field )
[migrated my answer from duplicate closed question]
The following excerpts are from the Python documentation about self:
As in Modula-3, there are no shorthands [in Python] for referencing the object’s members from its methods: the method function is declared with an explicit first argument representing the object, which is provided implicitly by the call.
Often, the first argument of a method is called self. This is nothing more than a convention: the name self has absolutely no special meaning to Python. Note, however, that by not following the convention your code may be less readable to other Python programmers, and it is also conceivable that a class browser program might be written that relies upon such a convention.
For more information, see the Python documentation tutorial on classes.
As well as all the other reasons already stated, it allows for easier access to overridden methods; you can call Class.some_method(inst).
An example of where it’s useful:
class C1(object):
def __init__(self):
print "C1 init"
class C2(C1):
def __init__(self): #overrides C1.__init__
print "C2 init"
C1.__init__(self) #but we still want C1 to init the class too
>>> C2()
"C2 init"
"C1 init"
Its use is similar to the use of this keyword in Java, i.e. to give a reference to the current object.
Python is not a language built for Object Oriented Programming unlike Java or C++.
When calling a static method in Python, one simply writes a method with regular arguments inside it.
class Animal():
def staticMethod():
print "This is a static method"
However, an object method, which requires you to make a variable, which is an Animal, in this case, needs the self argument
class Animal():
def objectMethod(self):
print "This is an object method which needs an instance of a class"
The self method is also used to refer to a variable field within the class.
class Animal():
#animalName made in constructor
def Animal(self):
self.animalName = "";
def getAnimalName(self):
return self.animalName
In this case, self is referring to the animalName variable of the entire class. REMEMBER: If you have a variable within a method, self will not work. That variable is simply existent only while that method is running. For defining fields (the variables of the entire class), you have to define them OUTSIDE the class methods.
If you don't understand a single word of what I am saying, then Google "Object Oriented Programming." Once you understand this, you won't even need to ask that question :).
First of all, self is a conventional name, you could put anything else (being coherent) in its stead.
It refers to the object itself, so when you are using it, you are declaring that .name and .age are properties of the Student objects (note, not of the Student class) you are going to create.
class Student:
#called each time you create a new Student instance
def __init__(self,name,age): #special method to initialize
self.name=name
self.age=age
def __str__(self): #special method called for example when you use print
return "Student %s is %s years old" %(self.name,self.age)
def call(self, msg): #silly example for custom method
return ("Hey, %s! "+msg) %self.name
#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)
#using them
print bob.name
print bob.age
print alice #this one only works if you define the __str__ method
print alice.call("Come here!") #notice you don't put a value for self
#you can modify attributes, like when alice ages
alice.age=20
print alice
Code is here
self is an object reference to the object itself, therefore, they are same.
Python methods are not called in the context of the object itself.
self in Python may be used to deal with custom object models or something.
It’s there to follow the Python zen “explicit is better than implicit”. It’s indeed a reference to your class object. In Java and PHP, for example, it's called this.
If user_type_name is a field on your model you access it by self.user_type_name.
I'm surprised nobody has brought up Lua. Lua also uses the 'self' variable however it can be omitted but still used. C++ does the same with 'this'. I don't see any reason to have to declare 'self' in each function but you should still be able to use it just like you can with lua and C++. For a language that prides itself on being brief it's odd that it requires you to declare the self variable.
The use of the argument, conventionally called self isn't as hard to understand, as is why is it necessary? Or as to why explicitly mention it? That, I suppose, is a bigger question for most users who look up this question, or if it is not, they will certainly have the same question as they move forward learning python. I recommend them to read these couple of blogs:
1: Use of self explained
Note that it is not a keyword.
The first argument of every class method, including init, is always a reference to the current instance of the class. By convention, this argument is always named self. In the init method, self refers to the newly created object; in other class methods, it refers to the instance whose method was called. For example the below code is the same as the above code.
2: Why do we have it this way and why can we not eliminate it as an argument, like Java, and have a keyword instead
Another thing I would like to add is, an optional self argument allows me to declare static methods inside a class, by not writing self.
Code examples:
class MyClass():
def staticMethod():
print "This is a static method"
def objectMethod(self):
print "This is an object method which needs an instance of a class, and that is what self refers to"
PS:This works only in Python 3.x.
In previous versions, you have to explicitly add #staticmethod decorator, otherwise self argument is obligatory.
Take a look at the following example, which clearly explains the purpose of self
class Restaurant(object):
bankrupt = False
def open_branch(self):
if not self.bankrupt:
print("branch opened")
#create instance1
>>> x = Restaurant()
>>> x.bankrupt
False
#create instance2
>>> y = Restaurant()
>>> y.bankrupt = True
>>> y.bankrupt
True
>>> x.bankrupt
False
self is used/needed to distinguish between instances.
Source: self variable in python explained - Pythontips
Is because by the way python is designed the alternatives would hardly work. Python is designed to allow methods or functions to be defined in a context where both implicit this (a-la Java/C++) or explicit # (a-la ruby) wouldn't work. Let's have an example with the explicit approach with python conventions:
def fubar(x):
self.x = x
class C:
frob = fubar
Now the fubar function wouldn't work since it would assume that self is a global variable (and in frob as well). The alternative would be to execute method's with a replaced global scope (where self is the object).
The implicit approach would be
def fubar(x)
myX = x
class C:
frob = fubar
This would mean that myX would be interpreted as a local variable in fubar (and in frob as well). The alternative here would be to execute methods with a replaced local scope which is retained between calls, but that would remove the posibility of method local variables.
However the current situation works out well:
def fubar(self, x)
self.x = x
class C:
frob = fubar
here when called as a method frob will receive the object on which it's called via the self parameter, and fubar can still be called with an object as parameter and work the same (it is the same as C.frob I think).
In the __init__ method, self refers to the newly created object; in other class methods, it refers to the instance whose method was called.
self, as a name, is just a convention, call it as you want ! but when using it, for example to delete the object, you have to use the same name: __del__(var), where var was used in the __init__(var,[...])
You should take a look at cls too, to have the bigger picture. This post could be helpful.
self is acting as like current object name or instance of class .
# Self explanation.
class classname(object):
def __init__(self,name):
self.name=name
# Self is acting as a replacement of object name.
#self.name=object1.name
def display(self):
print("Name of the person is :",self.name)
print("object name:",object1.name)
object1=classname("Bucky")
object2=classname("ford")
object1.display()
object2.display()
###### Output
Name of the person is : Bucky
object name: Bucky
Name of the person is : ford
object name: Bucky
"self" keyword holds the reference of class and it is upto you if you want to use it or not but if you notice, whenever you create a new method in python, python automatically write self keyword for you. If you do some R&D, you will notice that if you create say two methods in a class and try to call one inside another, it does not recognize method unless you add self (reference of class).
class testA:
def __init__(self):
print('ads')
def m1(self):
print('method 1')
self.m2()
def m2(self):
print('method 2')
Below code throws unresolvable reference error.
class testA:
def __init__(self):
print('ads')
def m1(self):
print('method 1')
m2() #throws unresolvable reference error as class does not know if m2 exist in class scope
def m2(self):
print('method 2')
Now let see below example
class testA:
def __init__(self):
print('ads')
def m1(self):
print('method 1')
def m2():
print('method 2')
Now when you create object of class testA, you can call method m1() using class object like this as method m1() has included self keyword
obj = testA()
obj.m1()
But if you want to call method m2(), because is has no self reference so you can call m2() directly using class name like below
testA.m2()
But keep in practice to live with self keyword as there are other benefits too of it like creating global variable inside and so on.
self is inevitable.
There was just a question should self be implicit or explicit.
Guido van Rossum resolved this question saying self has to stay.
So where the self live?
If we would just stick to functional programming we would not need self.
Once we enter the Python OOP we find self there.
Here is the typical use case class C with the method m1
class C:
def m1(self, arg):
print(self, ' inside')
pass
ci =C()
print(ci, ' outside')
ci.m1(None)
print(hex(id(ci))) # hex memory address
This program will output:
<__main__.C object at 0x000002B9D79C6CC0> outside
<__main__.C object at 0x000002B9D79C6CC0> inside
0x2b9d79c6cc0
So self holds the memory address of the class instance.
The purpose of self would be to hold the reference for instance methods and for us to have explicit access to that reference.
Note there are three different types of class methods:
static methods (read: functions),
class methods,
instance methods (mentioned).
The word 'self' refers to instance of a class
class foo:
def __init__(self, num1, num2):
self.n1 = num1 #now in this it will make the perimeter num1 and num2 access across the whole class
self.n2 = num2
def add(self):
return self.n1 + self.n2 # if we had not written self then if would throw an error that n1 and n2 is not defined and we have to include self in the function's perimeter to access it's variables
it's an explicit reference to the class instance object.
from the docs,
the special thing about methods is that the instance object is passed as the first argument of the function. In our example, the call x.f() is exactly equivalent to MyClass.f(x). In general, calling a method with a list of n arguments is equivalent to calling the corresponding function with an argument list that is created by inserting the method’s instance object before the first argument.
preceding this the related snippet,
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
x = MyClass()
I would say for Python at least, the self parameter can be thought of as a placeholder.
Take a look at this:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person("John", 36)
print(p1.name)
print(p1.age)
Self in this case and a lot of others was used as a method to say store the name value. However, after that, we use the p1 to assign it to the class we're using. Then when we print it we use the same p1 keyword.
Hope this helps for Python!
my little 2 cents
In this class Person, we defined out init method with the self and interesting thing to notice here is the memory location of both the self and instance variable p is same <__main__.Person object at 0x106a78fd0>
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hi(self):
print("the self is at:", self)
print((f"hey there, my name is {self.name} and I am {self.age} years old"))
def say_bye(self):
print("the self is at:", self)
print(f"good to see you {self.name}")
p = Person("john", 78)
print("the p is at",p)
p.say_hi()
p.say_bye()
so as explained in above, both self and instance variable are same object.

Why can't I call a method from my Python class?

I am learning Python and currently working with classes. I am trying to make a basic game to help learn it and am having a weird issue with calling methods
from it. I have the main.py file which creates an instance from the class in the Character.py file.
This is the Character.py file:
class Character:
name=""
def __init__(Name):
name=Name
def getName():
return name
This is the main.py file:
from Character import *
player = Character("James")
print(player.getName())
I am not sure what the issue is. This is the error I get:
Traceback (most recent call last):
File "C:\Users\dstei\Documents\Python\It 102\Final Project\Main.py", line
12, in <module>
print(player.getName())
TypeError: getName() takes 0 positional arguments but 1 was given
It is saying I am giving 1 positional argument but I don't see where I gave any. What am I missing?
Since you have a class with instance methods, you need to include the first argument (self by convention) to refer to the current instance. Also, make sure to set the variable as an instance variable by using self, the current instance:
class Character:
def __init__(self, Name): #self is the current instance
self.name=Name #set the variable on the instance so that every instance of Character has a name
def getName(self):
return self.name #refer to the name with the instance
Python internally passes the new instance of a class as the first argument to all the class methods, like this in languages such as Java. The error comes from the fact that Python passes the instance as the first argument internally but your getter is not defined to take an argument.
With the above code, when you call the method upon an instance, the instance is internally passed as the first argument and Python doesn't complain as you specify that it takes an argument, self, and name is set correctly on the instance.
Note: By convention, Python does not use camelCase, but underscores, so your getter should by convention look like this:
def get_name(self):
#...
Also see chepner's answer which explains why getters and setters aren't usually needed. Just get and modify the instance variable by using dot notation:
print(player.name) #get
player.name = "Jeff" #set
As others have mentioned, even instance method must be declared with an extra argument, typically named self (although that is a conventional, not a required, name).
class Character:
def __init__(self, name):
self.name = name
def get_name(self):
return name
However, Python does not have any kind of enforced visibility (such as public or private), so such trivial getters and setters aren't usually written. Documentation about which attributes you are "allowed" to modify are considered sufficient protection.
class Character:
def __init__(self, name):
self.name = name
c = Character("Bob")
print(c.name) # instead of c.get_name()
c.name = "Charlie" # instead of c.set_name("Charlie")
You are forgetting to add the parameter self. self is an object reference to the object itself, therefore, they are same. Python methods are not called in the context of the object itself. self in Python may be used to deal with custom object models or
class Character:
def __init__(self,name):
self.name=name
def getName(self):
return self.name
To see why this parameter is needed, there are so good answers here:
What is the purpose of self?

Python inheritance: when and why __init__

I'm a Python newbie, trying to understand the philosophy/logic behind the inheritance methods. Questions ultimately regards why and when one has to use the __init__ method in a subclass. Example:
It seems a subclass inheriting from a superclass need not have its own constructor (__init__) method. Below, a dog inherits the attributes (name, age) and methods (makenoise) of a mammal. You can even add a method (do_a_trick) Everything works as it ``should", it seems.
However, if I wanted to add a new attribute in the subclass as I attempt to do in the Cats class, I get an error saying "self" is not defined. Yet I used "self" in the definition of the dog class. What's the nature of the difference?
It seems to define Cats as I wish I need to use __init__(self,name) and super()__init__(name). Why the difference?
class Mammals(object):
def __init__(self,name):
self.name = name
print("I am a new-born "+ self.name)
self.age = 0
def makenoise(self):
print(self.name + " says Hello")
class Dogs(Mammals):
def do_a_trick(self):
print(self.name + " can roll over")
class Cats(Mammals):
self.furry = "True" #results in error `self' is not defined
mymammal = Mammals("zebra") #output "I am a new-born zebra"
mymammal.makenoise() #output "zebra says hello"
print(mymmmal.age) #output 0
mydog = Dogs("family pet") #output "I am a new-born family pet"
mydog.makenoise() #output "family pet says hello"
print(mydog.age) # output 0
mydog.do_a_trick() #output "family pet can roll over"
Explicit is better than implicit.
However, you can do below:
class Dogs(Mammals):
def __init__(self):
#add new attribute
self.someattribute = 'value'
Mammals.__init__(self)
or
class Dogs(Mammals):
def __init__(self):
#add new attribute
self.someattribute = 'value'
super(Mammals, self).__init__()
if I wanted to add a new attribute in the subclass as I attempt to do
in the Cats class, I get an error saying "self" is not defined. Yet I
used "self" in the definition of the dog class.
In your superclass, Mammal, you have an __init__ function, which takes an argument that you've chosen* to call self. This argument is in scope when you're in the body of the __init__ function - it's a local variable like any local variable, and it's not possible to refer to it after its containing function terminates.
The function defined on the Dog class, do_a_trick, also takes an argument called self, and it is also local to that function.
What makes these variables special is not their name (you could call them anything you wanted) but the fact that, as the first arguments to instance methods in python, they get a reference to the object on which they're called as their value. (Read that last sentence again a few times, it's the key to understanding this, and you probably won't get it the first time.)
Now, in Cat, you have a line of code which is not in a function at all. Nothing is in scope at this point, including self, which is why this fails. If you were to define a function in Cat that took an argument called self, it would be possible to refer to that argument. If that argument happened to be the first argument to an instance method on Cat, then it would have the value of the instance of Cat on which it had been called. Otherwise, it would have whatever got passed to it.
*you have chosen wisely!
Declarations at the top level of a Python class become class attributes. If you come from a C++ or Java background, this is similar to declaring a static member variable. You cannot assign instance attributes at that level.
The variable self usually refers to a specific instance of a class, the one from which the method has been called. When a method call is made using the syntax inst.method(), the first argument to the function is the object inst on which the method was called. In your case, and usually by convention, that argument is named self within the function body of methods. You can think of self as only being a valid identifier within method bodies then. Your assignment self.furry = True does not take place in a method, so self isn't defined there.
You have basically two options for achieving what you want. The first is to properly define furry as an attribute of the cat class:
class Cat(Mammals):
furry = True
# Rest of Cat implementation ...
or you can set the value of an instance variable furry in the cat constructor:
class Cat(Mammals):
def __init__(self):
super(Mammals, self).__init__(self)
self.furry = True
# Rest of Cat implementation ...
If you're getting into Python I highly recommend to read these two parts of the Python documentation:
Python classes
Python data model special methods (more advanced)
As pointed out in the other answers, the self that you see in the other
functions is actually a parameter. By Python convention, the first parameter in
an instance method is always self.
The class Cats inherits the __init__ function from its base class,
Mammals. You can override __init__, and you can call or not call the base
class implementation.
In case the Cats __init__ wants to call the base implementation, but doesn't want to care about the parameters, you can use Python variable arguments. This is shown in the following code.
Class declaration:
class Cats(Mammals):
def __init__(self, *args):
super().__init__(*args)
self.furry = "True"
See, for example, this Stack Overflow question for something about the star
notation for variable numbers of arguments:
Can a variable number of arguments be passed to a function?
Additional test code:
cat = Cats("cat")
print(vars(cat))
Output:
I am a new-born cat
{'name': 'cat', 'age': 0, 'furry': 'True'}
You can do something like in Chankey's answer by initiating all the variables in the constructor method ie __init__
However you can also do something like this
class Cats(Mammals):
furry = "True"
And then
cat = Cats("Tom")
cat.furry # Returns "True"
The reason you can't use self outside the functions is because self is used explicitly only for instances of the class. If you used it outside, it would lead to ambiguity. If my answer isn't clear please let me know in comments.
The __init__ method runs once on the creation of an instance of a class. So if you want to set an attribute on an instance when it's created, that's where you do it. self is a special keyword that is passed as the first argument to every method, and it refers to the instance itself. __init__ is no different from other methods in this regard.
"What's the nature of the difference": you define the method Dog.do_a_trick, and you receive self as an argument to the method as usual. But in Cat you've unintentionally (perhaps subconsciously!) attempted to work on the class scope -- this is how you'd set a class attribute whose value is identical for all cats:
class Cat(object):
sound = "meow"
It's different so you can have both options available. Sometimes (not all the time, but once in a while) a class attribute is a useful thing to have. All cats have the same sound. But much of the time you'll work with instance attributes -- different cats have different names; when you need that, use __init__.
Suppose you have a class named Person which has a method named get_name defined as :
class Person():
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
def get_name(self):
return self.first_name + ' ' + self.last_name
And, you create an instance of Person as p1. Now when you call the function get_name() with this instance, it will converts internally
Person.get_name(p1)
So, self is the instance itself.
Without self you can write above code as :
class Person():
first_name = None
last_name = None
def get_name(personobject):
return personobject.first_name + ' ' + personobject.last_name
What I am trying to say is the name self is a convention only.
And for inheritance, if you would like to have extra attributes in your subclass, you need to initiate your super class first and add your parameter as you wanted.
For example, if you want to create a subclass from Person named Boy with new attribute height, the you can define it as:
class Boy(Person):
def __init__(self, first_name, last_name, height):
super(Person, self).__init__(first_name, last_name)
self.height = height

Difference between methods and member variables?

class Animal(object):
"""Makes cute animals."""
is_alive = True
health = 'good'
def __init__(self, name, age):
self.name = name
self.age = age
# Add your method here!
def description(self):
print self.name
print self.age
hippo = Animal('Tom', '20')
sloth = Animal('Randy', '18')
ocelot = Animal('Birdman','57')
hippo.description()
print ocelot.health
print hippo.health
print sloth.health
The code above is from codecademy's python course. I am getting confused about some of the definitions surrounding OOP. If my understanding is correct, a function defined within a class is known as a method, which is why when it's called, for example like this: 'hippo.description()', the '()' are necessary because of the syntax involving functions.
However, I start to get confused with 'self.name' and 'self.age'. Are these also methods? I was wondering if they were perhaps member variables, but then wouldn't they be defined in the same way the variable 'health' was above? And if they aren't member variables, how come they can be accessed using dot notation in the same way as the member variables?
Cheers
I assume you're coming from a more traditional OOP programming language like C++ or Java.
health in the Animal class is what you would refer to as a static member variable, but in Python this is called a class attribute because it is unique to the class.
name in the Animal class is what you would refer to as a member or instance variable, and in Python this is called an instance attribute because it is unique to each instance of a class.
You use self to refer to attributes within its own class.
First of all the difference between class and instance attributes are answered elsewhere.
The difference between a method and member variables are that while they are both attributes, a method is a function while a member variable is not (or need not be). Also a method is normally a class attribute (at least if you use new style classes).
However in python functions are first class objects so this may confuse a little more: it's perfectly valid to assign a member variable with a function (or vice versa), but then that will become somewhat different because normally a method is shared among all objects, but when assigned to an instance it becomes private to that instance.
self.foo may be used to access both instance attributes or class attributes (if instance attribute does not exist).

Classes in python, how to set an attributes

When I write class in python, most of the time, I am eager to set variables I use, as properties of the object. Is there any rule or general guidelines about which variables should be used as class/instance attribute and which should not?
for example:
class simple(object):
def __init(self):
a=2
b=3
return a*b
class simple(object):
def __init(self):
self.a=2
self.b=3
return a*b
While I completely understand the attributes should be a property of the object. This is simple to understand when the class declaration is simple but as the program goes longer and longer and there are many places where the data exchange between various modules should be done, I get confused on where I should use a/b or self.a/self.b. Is there any guidelines for this?
Where you use self.a you are creating a property, so this can be accessed from outside the class and persists beyond that function. These should be used for storing data about the object.
Where you use a it is a local variable, and only lasts while in the scope of that function, so should be used where you are only using it within the function (as in this case).
Note that __init is misleading, as it looks like __init__ - but isn't the constructor. If you intended them to be the constructor, then it makes no sense to return a value (as the new object is what is returned).
class Person(object):
def __init__(self, name):
# Introduce all instance variables on __init__
self.name = name
self.another = None
def get_name(self):
# get_name has access to the `instance` variable 'name'
return self.name
So if you want a variable to be available on more than one method, make
it an instance variable.
Notice my comment on introducing all instance vars on __init__.
Although the example below is valid python don't do it.
class Person(object):
def __init__(self):
self.a = 0
def foo(self):
self.b = 1 # Whoa, introduced new instance variable
Instead initialize all your instance variables on __init__ and set
them to None if no other value is appropriate for them.
I try to imagine what I want the API of my class to look like prior to implementing it. I think to myself, If I didn't write this class, would I want to read the documentation about what this particular variable does? If reading that documentation would simply waste my time, then it should probably be a local variable.
Occasionally, you need to preserve some information, but you wouldn't necessarily want that to be part of the API, which is when you use the convention of appending an underscore. e.g. self._some_data_that_is_not_part_of_the_api.
The self parameter refers to the object itself. So if you need to use on of the class attributes outside of the class you would it call it as the name of class instance and the attribute name. I don't think there is any guideline on when to use self, it all depends on your need. When you are building a class you should try to think about what you will use the variables you creating for. If you know for sure that you will need that specific attribute in the program you are importing your class, then add self.

Categories