surface=self.surface
NameError: name 'self' is not defined
how can fix this Python Code is not defined
the code
class Rectangle:
def __init__(self, longueur=30, largeur=15):
self.lon = longueur
self.lar = largeur
self.nom = "rectangle"
def surface(self):
return self.lon * self.lar
surface=self.surface
def affichage(self):
print("rectangle=" + self.nom, "longueur=" + self.lon, "largeur=" + self.lar, "surface=" + self.surface)
class Carre(Rectangle):
def __init__(self, cote=10):
Rectangle.__init__(self, cote, cote)
self.nom = "carre"
r = Rectangle()
print(r)
c = Carre()
print(c)
At this line surface=self.surface you're trying to access a variable that does not exist in this scope. self has only been defined within the context of the various functions of your classes, and python doesn't know about it outside of those functions.
If you have an instance of Rectangle called for example rect, you can refer to its member function surface as rect.surface, or you can evaluate that function's value by calling rect.surface().
The key to understanding this is to know that objects can have many names. By convention, within the object we refer to the instance by the name self. Outside of the object, this would be confusing so we use names that tell us what object we're referring to. (Just as you might refer to yourself as "me", but you'd be confused if others used that same word to refer to you!)
Related
I am new to python ( started 1 week ago) and this is the first time i am doing coding so i am not able to understand fairly simple things as well.
can you explain this function to to me? i understand that a function is being defined with 2 input required self and my_object, but what is happening next? please explain like you would to a newbie.
class chain():
def __init__(self, my_object):
self.o = my_object
def __getattr__(self, attr):
x = getattr(self.o, attr)
if hasattr(x, '__call__'):
method = x
return lambda *args: self if method(*args) is None else method(*args)
else:
prop = x
return prop
Firstly, chain is not a Function, it's a Class.
A class in simple words is a definition of an object. (say Car)
Now the __init__ function of the class simply defines what's "in it" meaning what variables or properties does it has. Say for example a class Car:
class Car:
def __init__(self,maxspeed,color):
self.speed = maxspeed #So what's defined under **__init__** is a property of a class.
self.color = color
So here Class car has speed and color as variables(or attributes or properties)
Now there are methods , of simply function that control the behaviour of the object and it's functionalities.
class Car:
def __init__(self,maxspeed,color):
self.speed = maxspeed #So what's defined under **__init__** is a property of a class.
self.color = color
def accelarate(self): #Method to increase the speed of car object.
self.sepped = self.speed + 10
Now the method you have is a magical one , __getattr__
Say a scenario where you want to acess the brand of the car , now you haven't define self.brand in it's __init__ function so you you'll get an error when you call it like:
>>>red_car = Car(100,red) #Creating an object named red_car of class Car
>>>red_car.color
>>>'red'
>>>red_car.brand
>>> Attribute Error , Class car dosen't has attribute brand
Now remove this error when calling an undefined property for a object or put simple we tell tell the class what to do if an undefined variable is called we use the method __getattr__.
class Dummy(object):
def __getattr__(self, attr):
return attr.upper()
d = Dummy()
d.does_not_exist # 'DOES_NOT_EXIST'
d.what_about_this_one # 'WHAT_ABOUT_THIS_ONE'
In the above code does_not_exist property (attribute) is NOT define but still we are not getting error as the getattr catches it and does as instructed. In this case it catches attr capitalises it and returns it rather than throwing an error in your face.
The class chain has a constructor that takes an argument my_object and assigns it to an instance variable self.o.
The method __getattr__ is a special magic method that has been overridden to delegate calls to the initial my_object variable we first received.
The result of the delegated call is checked for a method named __call__. If present, it is called and the returned value is returned. If not, the value itself is returned as-is.
I'm trying to understand scope in nested classes in Python. Here is my example code:
class OuterClass:
outer_var = 1
class InnerClass:
inner_var = outer_var
The creation of class does not complete and I get the error:
<type 'exceptions.NameError'>: name 'outer_var' is not defined
Trying inner_var = Outerclass.outer_var doesn't work.
I get:
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
I am trying to access the static outer_var from InnerClass.
Is there a way to do this?
class Outer(object):
outer_var = 1
class Inner(object):
#property
def inner_var(self):
return Outer.outer_var
This isn't quite the same as similar things work in other languages, and uses global lookup instead of scoping the access to outer_var. (If you change what object the name Outer is bound to, then this code will use that object the next time it is executed.)
If you instead want all Inner objects to have a reference to an Outer because outer_var is really an instance attribute:
class Outer(object):
def __init__(self):
self.outer_var = 1
def get_inner(self):
return self.Inner(self)
# "self.Inner" is because Inner is a class attribute of this class
# "Outer.Inner" would also work, or move Inner to global scope
# and then just use "Inner"
class Inner(object):
def __init__(self, outer):
self.outer = outer
#property
def inner_var(self):
return self.outer.outer_var
Note that nesting classes is somewhat uncommon in Python, and doesn't automatically imply any sort of special relationship between the classes. You're better off not nesting. (You can still set a class attribute on Outer to Inner, if you want.)
I think you can simply do:
class OuterClass:
outer_var = 1
class InnerClass:
pass
InnerClass.inner_var = outer_var
The problem you encountered is due to this:
A block is a piece of Python program text that is executed as a unit.
The following are blocks: a module, a function body, and a class
definition.
(...)
A scope defines the visibility of a name within
a block.
(...)
The scope of names defined in a class block is
limited to the class block; it does not extend to the code blocks of
methods – this includes generator expressions since they are
implemented using a function scope. This means that the following will
fail:
class A:
a = 42
b = list(a + i for i in range(10))
http://docs.python.org/reference/executionmodel.html#naming-and-binding
The above means:
a function body is a code block and a method is a function, then names defined out of the function body present in a class definition do not extend to the function body.
Paraphrasing this for your case:
a class definition is a code block, then names defined out of the inner class definition present in an outer class definition do not extend to the inner class definition.
You might be better off if you just don't use nested classes. If you must nest, try this:
x = 1
class OuterClass:
outer_var = x
class InnerClass:
inner_var = x
Or declare both classes before nesting them:
class OuterClass:
outer_var = 1
class InnerClass:
inner_var = OuterClass.outer_var
OuterClass.InnerClass = InnerClass
(After this you can del InnerClass if you need to.)
Easiest solution:
class OuterClass:
outer_var = 1
class InnerClass:
def __init__(self):
self.inner_var = OuterClass.outer_var
It requires you to be explicit, but doesn't take much effort.
In Python mutable objects are passed as reference, so you can pass a reference of the outer class to the inner class.
class OuterClass:
def __init__(self):
self.outer_var = 1
self.inner_class = OuterClass.InnerClass(self)
print('Inner variable in OuterClass = %d' % self.inner_class.inner_var)
class InnerClass:
def __init__(self, outer_class):
self.outer_class = outer_class
self.inner_var = 2
print('Outer variable in InnerClass = %d' % self.outer_class.outer_var)
All explanations can be found in Python Documentation The Python Tutorial
For your first error <type 'exceptions.NameError'>: name 'outer_var' is not defined. The explanation is:
There is no shorthand for referencing data attributes (or other methods!) from within methods. I find that this actually increases the readability of methods: there is no chance of confusing local variables and instance variables when glancing through a method.
quoted from The Python Tutorial 9.4
For your second error <type 'exceptions.NameError'>: name 'OuterClass' is not defined
When a class definition is left normally (via the end), a class object is created.
quoted from The Python Tutorial 9.3.1
So when you try inner_var = Outerclass.outer_var, the Quterclass hasn't been created yet, that's why name 'OuterClass' is not defined
A more detailed but tedious explanation for your first error:
Although classes have access to enclosing functions’ scopes, though, they do not act
as enclosing scopes to code nested within the class: Python searches enclosing functions
for referenced names, but never any enclosing classes. That is, a class is a local scope
and has access to enclosing local scopes, but it does not serve as an enclosing local scope
to further nested code.
quoted from Learning.Python(5th).Mark.Lutz
class c_outer:
def __init__(self, name:str='default_name'):
self._name = name
self._instance_lst = list()
self._x = self.c_inner()
def get_name(self):
return(self._name)
def add_inner_instance(self,name:str='default'):
self._instance_lst.append(self.c_inner(name))
def get_instance_name(self,index:int):
return(self._instance_lst[index].get_name())
class c_inner:
def __init__(self, name:str='default_name'):
self._name = name
def get_name(self):
return(self._name)
outer = c_outer("name_outer")
outer.add_inner_instance("test1")
outer.add_inner_instance("test2")
outer.add_inner_instance("test3")
inner_1 = outer.c_inner("name_inner1")
inner_2 = outer.c_inner("name_inner2")
inner_3 = outer.c_inner("name_inner3")
print(outer.get_instance_name(index=0))
print(outer.get_instance_name(1))
print(outer._instance_lst[2]._name
print(outer.get_name())
print(inner_1.get_name())
print(inner_2.get_name())
test1
test2
test3
name_outer
name_inner1
name_inner2
name_inner3
In order to create a code, I have decided to create a python class to just define some variables with default value. you can see this as "struct" in C.
the file is name : ScreenStructure.py
Inside I have defined this code
class ViewIdleScreen():
def _init_(self):
self.menu_access = "id/no_id/21"
self.Call_app = "id/no_id/23"
self.Email_app = "idno_id/24"
self.Camera_app = "id/no_id/27"
self.Browser_app = "id/no_id/26"
self.Contacts_app = "id/no_id/9"
self.Calendar_app = "id/no_id/10"
self.Messaging_app = "id/no_id/11"
self.Notes_app = "id/no_id/12"
def Call_app(self):
return self.Call_app
In the main file, I have added :
from ScreenStructure import ViewIdleScreen
later in the code of the main file:
IdleScreenView = ViewIdleScreen()
print IdleScreenView.Call_app()
but instead of displaying "id/no_id/23" it display
<bound method ViewIdleScreen.Call_app of <ScreenStructure.ViewIdleScreen instance at 0x02A16990>>
First, you're naming __init__ _init_. This is wrong. You need two underscores.
Second, you're setting an attribute Call_app there, but that's the same name as the method you define later:
def Call_app(self):
return self.Call_app
In addition to being shadowed by the attribute (if __init__ were declared properly), this method returns the method itself, which is the bound method you're seeing.
Avoid the collision of attribute and method names, and name __init__ correctly
you should not make functions named the same as data members
hello = "hello world"
def hello():
print "goodbye!"
print hello
often times people will make a variable name preceded by an underscore or something
class X:
def __init__(self,*args):
self._x = "yellow"
def x(self):
return self._x
but as #mhlester points out a main problem is that you named __init__ incorrectly
I'm new to python, and it really confused me.
I want to write something like
class line :
points = []
def add(self, point) :
self.points.append(point)
line1 = line()
line2 = line()
line1.add("Some point")
print line2.points
Output: ['Some point']
And the result is like they refers to the same list.
But I do want a object member not a class member.
And I tried, if points is int, or some other simple type it works fine.
Besides, I know if I write
def __init__(self) :
self.points = []
it will also work, but I don't get why they are pointing to same list by default.
ps. I know writing a init will work.
class line :
name = "abc"
def changename(self, name) :
self.name = name
line1 = line()
line2 = line()
line1.changename(123)
print line2.name
But the code above output "abc"
So I don't understand why same kind of declaration act different by type.
Because in this case
class line :
points = []
points is a class member. It belongs to the class, and since line1 and line2 are of the same class, points is the same list.
So you are right in using
def __init__(self) :
self.points = []
instead to create an instance member which is tied to the instance, not the class.
To answer your edit
If you write:
def changename(self, name) :
self.name = name
you override your class member and create a new instance member using self.name = name.
To get back to your first example, it would be like writing:
def add(self, point) :
self.points = self.points + [point]
The first syntax:
class line :
points = []
makes points a class attribute. Therefore, it will be shared between all instances of the class.
To make sure that an attribute belongs to a class, you should do as follows:
class line(object) :
def __init__(self):
self.points = []
i.e., creating the attributed only in __init__, when a new instance is created.
As others have already explained, and as you apparently already understand, the following creates a class attribute, shared by every instance:
class line:
points = []
When you reference this attribute in your code, Python attempts to find it the current scope, and then follows the enclosing scopes. So if you call self.points.append(), you are indeed changing the points class attribute.
When you assign to self.points in your code, you are defining a new points instance attribute. So in your second example when points is a string, the changename function actually creates a new instance attribute when called.
You can try the following:
print line.name # prints the class attribute
print line1.name # prints the class attribute
print line2.name # prints the instance attribute
You will notice that calling changename did create a new instance attribute, while the class attribute is left unchanged. As changename was never called on line1, a reference to its name will resolve to the line class attribute.
Can you please clarify about the perimeter variable in the below class.
I understand that the self.vertices is to a particular instance. Since perimeter is not defined with self, does that mean its a class variable here? Then is it not common to all the instances?
Is it not the right way to code the perimeter as self.perimeter, so its aptly declared to each instance?
This code is from a book.
Polygon.py
import math
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def distance(self, p2):
return math.sqrt((self.x-p2.x)**2 + (self.y-p2.y)**2)
class Polygon:
def __init__(self):
self.vertices = []
def add_point(self, point):
self.vertices.append((point))
def perimeter(self):
perimeter = 0
points = self.vertices + [self.vertices[0]]
for i in range(len(self.vertices)):
perimeter += points[i].distance(points[i+1])
return perimeter
>>> square = Polygon()
>>> square.add_point(Point(1,1))
>>> square.add_point(Point(1,2))
>>> square.add_point(Point(2,2))
>>> square.add_point(Point(2,1))
>>> square.perimeter()
4.0
New type
import math
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def distance(self, p2):
return math.sqrt((self.x-p2.x)**2 + (self.y-p2.y)**2)
class Polygon:
def __init__(self):
self.vertices = []
def add_point(self, point):
self.vertices.append((point))
def perimetermethod(self):
self.perimeter = 0
points = self.vertices + [self.vertices[0]]
for i in range(len(self.vertices)):
self.perimeter += points[i].distance(points[i+1])
return self.perimeter
if __name__=='__main__':
p1 = Polygon()
p1.add_point(Point(1,1))
p1.add_point(Point(1,2))
p1.add_point(Point(2,2))
p1.add_point(Point(2,1))
print(p1.perimetermethod())
Assigning a new variable with some_name = ... always creates the variable in the innermost enclosing scope (unless global or nonlocal are in play, but they're not relevant here). Assigning a new attribute name on an object creates the attribute on that object.
So self.foo = 1 assigns an attribute named foo on the object currently referred to by self. Conventionally, the name self is used as the first parameter to a method, which receives the object on which the method was invoked. So "defining a variable with self" isn't anything special; it's just the ordinary rules about assigning to attributes on existing object. Any attributes that exist in instance object itself obviously have to be specific to that instance.
perimeter = 0 inside the perimeter method of the Polygon class creates a variable in the innermost enclosing scope. That's the perimeter method, so it creates a local variable. A local variable only exists for the duration of the function call, so it's neither a class variable nor an instance variable. You can't access it from anywhere except within the scope of that particular method (and it has a new completely independent value on each invocation), so it can't be common to all the instances. But neither can you access a different value for it on each particular instance, so it's not an instance variable either.
If you had perimeter = 0 outside a method, in the class block itself, then the innermost enclosing scope would be the class block. That would create a "class variable", which is just an attribute on the class object. If an attribute is on a class, then obviously it can't be specific to any instance, because there's only one class but there can be any number of instances. As an aside, this is exactly what the __init__, add_point, and perimeter methods of the Polygon class are; they were assigned (with a def statement) in a class block, so they became attributes of the class object.
Summary:
self.foo = 1 is assigning to an attribute on the object currently referenced by self (this is usually the "current instance")
foo = 1 in a class block is creating a class attribute of the class being defined
foo = 1 in a def block is creating a local variable of the function being defined
But you shouldn't really memorise it that way. They're just special cases of:
Assigning to a dotted name like foo.bar.baz = 1 is writing to an attribute of an object
Assigning to a simple name like foo = 1 is writing to a variable in the innermost enclosing scope
No, that means that it's local. Also, you don't want to use self.perimeter since it will shadow the method with the same name.
In your code, there are two things called perimeter. One is a method on the Polygon class. The other is a local variable inside that method. There are no class attributes in your code.