I am a newbie and have confused learning OOP on python. I am trying to inherit class also using super, but it didn't work as expected.
here my code.
parent.py
class Sale(http.Controller):
def cart(self, **post):
order = request.website.sale_get_order()
....
return request.render("website_sale.cart", values)
child.py
import Sale as sale
class SaleExtend(sale):
def cart(self, **post):
if order:
# do something
....
return super(SaleExtend, self).cart(**post)
I got an error,
AttributeError: 'Sale (extended by SaleExtend)' object has no attribute 'order'
if I just use pass its work correctly, but how to get order value from a parent?
or I did it wrong.
You have no instance nor a class variable order:
class Sale(http.Controller):
def cart(self, **post):
# FUNCTION SCOPE - exists only inside the function
order = request.website.sale_get_order()
....
return request.render("website_sale.cart", values)
Class variables are created like so:
class Ale():
content = "Lager" # this is shared between all instances -> "static"
Instance variables are created like so:
class Ale():
def __init__(self, ale_type):
self.content = ale_type # this is different for each instance unless you
# create multiple instances with the same ale_type
# but they are still "independent" of each other
Function scope variables are creates like so:
class Ale():
# ....
def doSomething(self):
lenContent = len(self.content) # function scope
print( self.content, lenContent )
def doElse(self):
print(lenContent) # NameError - does not exist in scope
See Resolution of names and Short description of the scoping rules?
Related
I recently switched to Python from Java for development and is still not used to some of the implicitness of Python programming.
I have a class which I have defined some class variables, how can I access the class variables within a method in Python?
class Example:
CONSTANT_A = "A"
#staticmethod
def mymethod():
print(CONSTANT_A)
The above code would give me the error message: "CONSTANT_A" is not defined" by Pylance.
I know that I can make this work using self.CONSTANT_A, but self is referring to the Object, while I am trying to directly access to the Class variable (specifically constants).
Question
How can I directly access Class variables in Python and not through the instance?
In python, you cannot access the parent scope (class)'s fields from methods without self. or cls..
Consider using classmethod:
class Example:
CONSTANT_A = "A"
#classmethod
def mymethod(cls):
print(cls.CONSTANT_A)
or directly accessing it like Classname.attribute:
class Example:
CONSTANT_A = "A"
#staticmethod
def mymethod():
print(Example.CONSTANT_A)
for static method, you can access the class variable by <class_name>.<variable>.
>>> class Example:
... CONSTANT_A = "A"
... #staticmethod
... def mymethod():
... print(Example.CONSTANT_A)
...
>>>
>>> x = Example.mymethod()
A # print value
I have this class hierarchy
class ParentMeta(type):
def __new__(v1, name, b, x):
# some code
return super(ParentMeta, v1).__new__(v1, name, b, x)
and then
class ServiceMeta(ParentMeta, AnotherServiceMeta):
pass
The ServiceMeta is normally used as a decorator in add_metaclass i.e.,
#add_metaclass(ServiceMeta)
class MyService(object):
""" Code
The question i want to ask that how can i pass name attribute here? The name attribute is part of ParentMeta.
EDIT:
Link to add_metaclass documentation: https://six.readthedocs.io/#six.add_metaclass
By default, the ServiceMeta is picking up MyService as name for the class. I want to modify this behavior. For that reason i want to pass name value in decorator.
The source code below will raise the exception on the last line. Why the exception is raised if they are two different objects?
class BaseClass(object):
accounts = dict()
def AddAccount(self, account_id, account_var):
if account_id in self.accounts.keys():
raise Exception('Account already exists')
self.accounts.update({account_id: account_var})
class Class1(BaseClass):
pass
class Class2(BaseClass):
pass
ACCOUNT_ID = '123'
c1 = Class1()
c2 = Class2()
c1.AddAccount(ACCOUNT_ID, 'abc')
c2.AddAccount(ACCOUNT_ID, 'abc')
I've tried call the constructor inside each class, but that don't solve the problem. I did like this inside each class:
def __init__(self):
super().__init__()
It looks like the BaseClass is always a static object. When I change in one object, it will change in the other one.
You've defined accounts as a variable of the class, instead of an instance variable. You should instead define accounts in the __init__ method of your base class so that it is instantiated with a different reference for each instance of the class that you create.
class BaseClass(object):
def __init__(self):
self.accounts = dict()
def AddAccount(self, account_id, account_var):
if account_id in self.accounts.keys():
raise Exception('Account already exists')
self.accounts.update({account_id: account_var})
You've defined a class variable in the body of your BaseClass.
Even if you reference it with self.accounts it's not an instance variable.
If you wanted an instance variable, for example, you should initialize it in __init__() with self.accounts = {}
Let me give a brief explanation of the issue:
I have a server object with several functionalities.
all functionalities have some common code, so this warrants a functionalities base class
Each functionality has its own set of constants, defined in a constants class within the functionality.
The functionality base class has a set of common constants as well.
here is a sample code:
class server:
class base_func:
class common_consts:
name = "name"
def validate(self):
pass
def execute(self):
pass
class func1(base_func):
class consts:
new_name = base_func.common_consts.name #this is where the problem occurs
def get_result(self):
self.validate()
self.execute()
so when i try to use the common_consts from base_func, in func1.consts, I get the following error:
NameError: global name 'base_func' is not defined
I do not know why this happens. Can someone help?
Is there a limitation to the scope of nesting in python, especially 2.7
Also if i remove the top level server class, and have the functionality classes as independent classes, everything seems to work fine. The example of the working code is here:
class base_func:
class common_consts:
name = "name"
def validate(self):
pass
def execute(self):
pass
class func1(base_func):
class consts:
new_name = base_func.common_consts.name #this is where the problem occurs
def get_result(self):
self.validate()
self.execute()
This leads me to believe that there definitely exists some limitation to the nesting depth and namespace scopes in python. I just want to be sure before i make changes to my design.
class server:
class base_func:
class common_consts:
name = "name"
def validate(self):
pass
def execute(self):
pass
# base_func and func1 are at same, level. So, here you can directly use base_func and func1 anywhere
# at top level of the server class
class func1(base_func):
class consts:
new_name = base_func.common_consts.name # this is where the problem occurs
def get_result(self):
self.validate()
self.execute
For a class(classes have their own namespace), variable lookup works like this:
While parsing the class body any variable defined inside the class body can be access directly, but once
it is parsed it becomes a class attribute.
As, the class base_func is inside server class which is still being parsed the func1(base_func) will work fine.
But, for class consts base_func is not at the same level. So, after looking the variable in its body it will directly jump
to its enclosing scope, i.e global namespace in this case.
A fix will be to do the assignement like this:
class server:
class base_func:
class common_consts:
name = "name"
def validate(self):
pass
def execute(self):
pass
class func1(base_func):
class consts:
pass
def get_result(self):
self.validate()
self.execute
func1.consts.new_name = base_func.common_consts.name
You've hit a problem with class scope. The class scope is never made available except to operations that directly occur in the class scope. This is why you can't call method within another method without referencing self.
eg.
class A(object):
def f(self):
pass
def g(self):
f() # error, class scope isn't available
The same is true when you create a nested class. The initial class statement class ClassName(Base): has access to the class scope, but once in the nested class scope you lose access to the enclosing class scope.
Generally, there is no good reason to nest classes in python. You should try to create all classes at module level. You can hide internal classes by either placing them in a sub module or all prefixing them with an underscore.
class _BaseFunctionality(object):
# common constants
name = "name"
value = "value"
def execute(self):
return (self.name, self.value)
class _SpecificFunctionality(_BaseFunctionality):
# specific constants
# override value of value attribute
value = "another_value"
def get_result(self):
assert self.name == "name"
return self.execute()
class Server(object):
functionality = _SpecificFunctionality()
assert _BaseFunctionality.value == "value"
assert _SpecificFunctionality.value == "another_value"
assert Server().functionality.get_result() == ("name", "another_value")
I am newbie in Python.I know this question is useless.But I am frustrated with my issue.I have 2 methods defined in my base class Animals.When I try to call the base methods in my inherited classes it shows these error:
NameError: name 'display_name' is not defined
class Animals():
def display_name(self):
print ('Name is Mr.X')
def display_age(self):
print('Age is 25')
class Name(Animals):
display_name(self)
class Age(Animals):
display_age(self)
n=Name()
a=Age()
n.display_name()
a.display_age()
You need to refer to the display_name function with a self prefix instead of passing self as an argument.
Also, as noted by Antimony, you need to call the display_name from within a function that is associated with an instance of the class (inside a function that accepts the self argument).
Code that appears outside a method function but inside a class is associated with the whole class, not with any particular instance of that class - using the self variable in this context has no meaning - if you create multiple objects from the class which one does it refer to?
class Animals():
def display_name(self):
print ('Name is Mr.X')
def display_age(self):
print('Age is 25')
class Name(Animals):
def call_display_name(self):
self.display_name()
class Age(Animals):
def call_display_name(self):
self.display_age()
Name().call_display_name()