Python global name not defined error? - python

I am calling a function to validate form in python, but I am getting error :
user = valid_username(username)
NameError: global name 'valid_username' is not defined.
code:
class MainPage(Handler):
def valid_username(self,username):
print USER_RE.match(username)
return USER_RE.match(username)
def render_front(self,username="",password="",error=""):
logins = db.GqlQuery("SELECT * FROM logindb")
self.render("login.html",username=username,password=password,error=error,logins=logins)
def get(self):
self.render_front()
def post(self):
username = self.request.get("userID")
password = self.request.get("pass")
user = valid_username(username)
# pas = isvalid_password(password)
if user and password:
a = logindb(username = username,password=password)
a.put()
self.redirect("/")
else:
error = "we need both username and password"
self.render_front(username,password,error)

valid_username is a class method which means that its name is in the class namespace. But python doesn't look variables up in the class namespace unless you explicitly tell it to do so. When python sees:
user = valid_username(username)
it looks for "valid_username" in the local method scope and then the module scope (confusingly called "global"). Since its not in either, you get the error.
When you define a class method like:
def valid_username(self,username):
the self variable is in the local function scope and refers to the class instance data. You use self to find the method:
user = self.valid_username(username)
Now, python looks up self in the local function scope, realizes its a class instance reference, and continues the lookup by first checking if the name is in the instance variables and then falling back to the class namespace (finally!) where your method is defined.

Related

When I use one base class for two different classes, and change a variable within one class instance, the variable in the other class is also changed?

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 = {}

How to access user uid from anywhere in the code?

I'm trying to access the currently logged in user eslewhere in my code (i.e in other classes). I've managed to do this to some extent with global (frowned upon I know but didn't find any other way), as shown below:
class Login(Screen):
def login(self, email, password):
try:
global user
user = auth.sign_in_with_email_and_password(email, password)
print(user['localId']) #This is the users uid
class SelectChat(Screen):
def __init__(self, **kwargs):
super(SelectChat, self).__init__(**kwargs)
grid = GridLayout(cols=1)
self.add_widget(grid)
docs = db.collection(u'users').where(u'value', u'==', True).stream()
for doc in docs: # cycle through database and create Buttons for each value found
dict = doc.to_dict()
btn = Button(text="{} {}".format(dict['first_name'], dict['last_name']), id=doc.id)
btn.bind(on_release=self.move_to_chat(doc.id))
grid.add_widget(btn)
def move_to_chat(self, *args):
group_id = str(user['localId']) + str(doc.id) # This is where I'm trying to access the user variable but it's getting called on startup due to the above ```btn.bind()``` call.
print(group_id)
MDApp.get_running_app().sm.current = "chat"
The problem I'm having now is that I want to access the user['localId'] value in the __init__ method of another class. As this is run when as soon as the app has loaded the login method hasn't started and therefore there's no user variable.
Error message: NameError: name 'user' is not defined

Python 2.7 Ineritance get parent method properties

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?

Multi-Level nested classes with inheritance among inner classes

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")

Pass data to imported Python program

What I want to do is something like this:
Script1:
import script2
def calc():
instance = script2.User()
instance.user = "me"
script2.vital_function()
Script2:
class User():
user = ""
def vital_function():
# Complex function that uses the User class
So I want to be able to run script2.py inside script1.py with variables set in script1.py. I don't think I have explained myself very clearly. Ask me if something is unclear.
If user must be an object attribute, you can override the init method for the class (its constructor) and pass it the value you need it to store.
class User():
def __init__(self, user):
self.user = user
def vital_function():
...
If, instead, it must be some static value that you share among all the instances of User, either you monkey-patch it as you did, or you define a setter method
class User():
user = ""
#staticmethod
def set_user(user):
User.user = user
but I guess the first way makes more sense.
Are we missing something from your requirements?

Categories