Unresolved reference in class method - python

I don't think it is because of the scope of the function, but I get a
Unresolved reference at get_all_predicates(examples).count(predicate_list[0])
inside get_entropy_of_attributes(examples, predicate_list) function in my class Tree:
class Tree:
def get_examples(examples, attributes):
for value in examples:
yield dict(zip(attributes, value.strip().replace(" ", "").split(',')))
def get_all_predicates(examples):
return [d['Predicate'] for d in examples]
def get_entropy_of_attributes(examples, predicate_list):
get_all_predicates(examples).count(predicate_list[0])
return 0
examples = list(get_examples(all_examples, name_of_attributes))
predicate_list = list(set(get_all_predicates(examples)))
get_entropy_of_attributes(examples, predicate_list)
all_examples is a list of dictionary and name_of_attributes is a list, that holds values imported from a text file.
all_examples = [{'P_Length': '1.4', 'P_Width': '0.2', 'Predicate': 'I-setosa', 'Sepal_Width': '3.5', 'S_Length': '5.1'}, ...]
name_of_attributes = ["Check","P-Width"]
Any help?

Classes do not have scopes, only namespaces. This means that functions defined within them cannot see other class variables automatically.
class Foo(object):
var = 1 # lets create a class variable
def foo():
print(var) # this doesn't work!
To access a class variable, you need use attribute syntax: either Foo.var (to access via the class) or, if you're writing an instance method, with self.var (to access via the current instance, which will be passed in as the first argument).
class Bar(object):
var = 1
def bar1():
print(Bar.var) # works
def bar2(self):
print(self.var) # also works, if called on an instance, e.g. `Bar().bar2()`
With this kind of setup you can almost fix your current code (but not quite).
def get_entropy_of_attributes(examples, predicate_list):
Tree.get_all_predicates(examples).count(predicate_list[0]) # name the class
return 0
If you call this after the class is fully initialized, it will work without any exceptions (though it's implementation seems a bit nonsensical). However, it doesn't work when you call it to define a class variable, as your current code does. That's because the class object is only created and bound to the class name after all of the class body has been run.
I think the fix for that is probably to redesign your class in a more conventional way. Rather than having class variables set up based on various globals (like all_examples), you should probably create instances of your class by passing in arguments to the constructor and making the other variables you calculate from them instance attributes. I'd try to write it out, but frankly I don't understand what you're doing well enough.

If you want to call class methods, you have to call them with self, e.g.
class myClass:
def __init__(self):
pass
def get_all_predicates(self):
print('asd')
def do_something(self):
self.get_all_predicates() # working
get_all_predicates() # → Unresolved reference
test = myClass()
test.do_something()
See this link for examples for Python classes.

Related

Why can't I invoke a static method inside the class body?

class StaticClass(object):
words = []
StaticClass.init()
#staticmethod
def init(file_name):
...
words.append('word')
...
#staticmethod
def fun():
print('fun')
test = StaticClass()
The error message is:
StaticClass.init()
NameError: name 'StaticClass' is not defined
Why can't I call the static function inside the class?
I want to use a class to do this and also want users to be able to do:
StaticClass.fun()
How to achieve the effect?
Why can't I call the static function inside the class?
As said in the comments, class bodies are executed in Python. It is like a zero-argument function that automatically runs once; then invokes type, passing it the class name, bases and a dict of class attributes from the local variables of that function; and only then assigns the result from type (i.e., a class object) to the name.
You can even put logic and other statements in there:
import random
# a class that sometimes fails to exist when you import the module.
class spam:
if __name__ != '__main__':
1 / random.randrange(3)
else:
print("thank you for running this as the main script.")
def __init__(self):
# etc.
As such, names have to be in scope. At the time that this code is running - because it runs immediately and automatically, rather than being delayed like a function - there isn't a StaticClass until after this code has completed. Consequently, the code inside can't reference the class itself.
To solve this, simply move the call to the end:
class StaticClass(object):
words = []
#staticmethod
def init(file_name):
...
words.append('word')
...
#staticmethod
def fun():
print('fun')
StaticClass.init()
By the time the body of the StaticClass class is being executed there is no reference to StaticClass, it doesn't exist yet. The body of the class is executed inside a namespace which is a dictionary. After that a new instance of type type which is here named StaticClass is created using that populated dictionary and added to the global namespaces. That's what class keyword roughly does in simple form.
Actually I don't know why you want this to work. Others already suggested best ways to deal with it but here is workaround if you want to call staticmethod as an initializer function when the class is being created and call it inside the class:
class StaticClass(object):
words = []
#staticmethod
def init(file_name, words=words):
words.append(file_name)
init.__get__(init)('word')
#staticmethod
def fun():
print('fun')
test = StaticClass()
StaticClass.fun()
print(StaticClass.words)
output:
fun
['word']
Yes it's really a mess, I just want to make it work to say why it didn't work before. You need to call init.__get__ because staticmethods are not callable. (I'm in Python 3.9.7) This way you init executed when the class is created. Also words is not accessible because the scope of the class is not enclosed the scope of the body of init, so I use it's reference as default parameter.

Call a method in an outer object from an inner object

Class A instantiates an object from Class B as a member variable. How can this class B object call methods from the Class A object? When I execute the program below I would expect to get a "Hello" printed, but I get an error instead saying "name 'a' is not defined"
What is the issue here and how can I fix it?
class B:
def __init__(self):
a.say_hello()
class A:
other = None
def __init__(self):
self.other = B()
def say_hello():
print("Helo")
a = A()
Python references are one-way. You'll need to retain a reference in the reverse direction for this to work.
class B:
def __init__(self, outer):
outer.say_hello()
class A:
# other = None # (see below)
def __init__(self):
self.other = B(self)
def say_hello():
print("Helo")
a = A()
If you need outer for more than just the constructor, you can store it in an instance variable.
You also don't need the other = None line. In Python, you don't need to declare your instance variables at the top of the class like you do in Java or C++. Instead, you just use self. to assign to them and they start existing. other = None in that scope makes a class variable, similar to static variable in Java, that can be referenced by A.other (Note the capital A; this is the class itself, not an instance of it).
There are situations where you might want to declare instance variables at the top of the class in some form or another (__slots__ and PEP 484 annotations are the main two), but for simple classes when you're starting out, it's not necessary, and an assignment like that will not do what you expect.

use variables created in the init of a class, into staticmethod functions

I have a class; which in its constructor, is assigning a variable.
I want to call this variable, from a function inside this class, which is a staticmethod. I can't seem to find the right way to do this.
class myclass:
def __init__(self):
myvariable = os.cwd()
#staticmethod
def myfunction(someparameter)
print(myclass.myvariable)
print(someparameter)
When I run the class from python, I get an error that myvariable does not exist
mytestclass = myclass
myclass.myfunction("foo")
I tried to use both self.myvariable and myvariable, but it does not make any difference. I didn't use #classmethod because if I would call cls.myvariable, I would not get that specific instance of myclass; and if I have multiple instances I may end up with issues.
myVariable is only a temporary variable in this case, that only is visible in the __init__ method, not even in other methods of the class. You could use myclass.myvariable also in the __init__ method.
You can do it as follows. I also added an instance counter:
class myclass:
counter= 0
def __init__(self):
myclass.myvariable = os.cwd()
myclass.counter+= 1
#staticmethod
def myfunction(someparameter):
print(myclass.myvariable)
print(myclass.counter)
print(someparameter)

Can I access a class variable using object of that class

I have two very basic object oriented question
1) Can we modify a class variable with member function?
For example
class test:
'''test class'''
idd=0
def __init__(self,mark,subject):
self.markk=mark
self.subjectt=subject
def display(self):
print "the display is",self.markk,self.subjectt;
stud1=test(30,'maths')
stud2=test(40,'english')
when i tried to modify class variable idd using the object stud1.idd=9;, the variable didnt modified. test.idd=9 modified the variable.
Can someone explain me why it is not possible to modify a class vars from a object?
2) Also in the above snippet, when I added a keyword global with the class var idd like
class test:
'''test class'''
global idd;
idd=0;
print test.idd
it threw error like name class test don't have attribute idd.
But when I commented out the global idd, it displayed value.
So is global keyword not supported in class?
can someone help me to get some idea on these two question as this is my basic step to object oriented concept..
I think that you're not understanding that python looks up values by looking at a "chain" of objects1. When you do value = self.foo, python will first look for foo on the instance. Then it will look on the class. Then it will look on the super-classes (in their "Method Resolution Order").
When you write:
self.foo = 'bar'
Python simply puts a foo on the instance. So now subsequent lookups on that instance will give you 'bar' even if foo is also defined on the class. Also note that since foo gets put on the instance, no changes are visible on the class.
If you want to update the class in a particular method, you might be able to use a classmethod:
class Foo(object):
idd = 0
#classmethod
def increment_idd(cls):
cls.idd += 1
f = Foo()
f.increment_idd()
print(Foo.idd)
print(f.idd)
This doesn't work if you need access to self however. In that case, you'll need to get a reference to the class from the instance:
class Foo(object):
idd = 0
def increment_idd(self):
cls = type(self)
cls.idd += 1
f = Foo()
f.increment_idd()
print(Foo.idd)
print(f.idd)
1If you know javascript, it's actually not too much different than javascript's prototypical inheritance
As long as it is a public variable you should be able to.

NameError: name 'self' is not defined - when trying to post values to different queues

is this correct way of doing.i am a newbie python
class main(threading.Thread):
queueLock = threading.Lock()
EppQueue = Queue.Queue(1)
CrQueue = Queue.Queue(1)
EPP = threading.Thread(name='EPP', target=EPP, args=(0,EppQueue,))
cr = threading.Thread(name='cr', target=CR, args=(0,CrQueue,))
EPP.setDaemon(True)
EPP.start()
Cr.start()
self.send_queue("EppQueue","sss")
self.send_queue("CrQueue","ssds")
def send_queue(self,queuename,qvalue,b=None):
if b is None:
b = self.queuename
self.queueLock.acquire()
self.b.put(qvalue)
self.queueLock.release()
when i run this i get NameError: name 'self' is not defined ???
The variable self (the first argument to a class method - you can use any name for it) is meant to refer to a class instance (also called an object). You use self where self is not defined, right out in the class where no specific object is yet known.
When the code queueLock = threading.lock() ... etc, is executed you are not in a class object (instance) but in the context of the class, so your lock will be the same for all objects of the class.
About send_queue, it's defined and known to all objects via the class, so you do not need to use self. to access it.
If you want some code to be executed at instance creation put it in __init__.
class main(threading.Thread):
def __init__(self):
self.queueLock = threading.Lock()
.. some code ...
send_queue("EppQueue","sss")
send_queue("CrQueue","ssds")
You cannot use "self" for a Class variable / function..You can use "self" for an instance of Class...
For example :
class A():
x=3
class B():
def __init__(self):
self.x=3
A.x is a class variable. B's self.x is a instance variable..!!
Also for calling a function of Class..the best practice is to make an instance (Object) of that Class and Call the function with that Object..!!
Like :
x = main()
x.send_queue()
And for code to be run on "instance" creation, put that code in
__init__(): function
Please make sure that the send_queue function is part of the main class. The self is like this pointer in C++ and needs to be associated with a class. The send_queue function should be indented along with the main class

Categories