python __init__ class attribute, when will class Test be ready? - python

First program in book fluent Python. I simplified the program.
class Test:
a = 15
def __init__(self):
self.att = a
t = Test()
print(t.att)
It didn't work, and if i use
self.att = Test.a
then it worked.
Why should I always use Test.a even in class Test?
I learned java, and I don't have to do so.
Also, here comes another problem.
class Test:
a = 15
def __init__(self, b=Test.a):
self.att = b
t = Test()
print(t.att)
It didn't work. I searched on the site.
And is the reason that:
default arguments should be defined while function definition, not till being called?
And since
self.att = Test.a
worked, so function content will be checked for valid till being called?
Am I right?
Class Test will be ready after #1, but before, I used Test.a, because it didn't check function content before being called. right?
class Test:
a = 15
def __init__(self):
self.att = Test.a
#1
t = Test()
print(t.att)

Members like that need to be accessed like this: self.a (even in the __init__ method)
class Test:
a = 15
def __init__(self):
self.att = self.a
t = Test()
print(t.att)

I learned java, and I don't have to do so.
But if you compare Java with Python, you will notice that you will have to prefix self for every instance member, and you actually need your methods to take that self argument in all the time. So you cannot really expect Java behavior here.
But just like with methods or instance variables, you can access class members using self as well:
class Test:
a = 15
def __init__(self):
self.att = self.a
At runtime of __init__, self will refer to the instance of your Test type. So when you want to access anything on the instance, you need to do that on self. For class members, all its members are also visible on the instance (unless they are hidden by instance members), so self.a works just like Test.a works. You can also try this with your created instance t: t.a will also work even though there is no instance member a.

The reason is __init__ is executed on object creation; inside your __init__ function scope there is no a variable defined. How should it know you mean the a defined in the class?
When stating Test.a you explicity tell python to use the class attribute. When you are using self.a Python uses the MRO lookup process to find the a attribute.
class Test:
a = 15
def __init__(self):
self.att = self.a
#1
t = Test()
print(t.att)

Related

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.

Why is it not possible to assign a reference to a class to a class variable?

Pretty much what the title says but I will put some example code to clarify.
I would like to know why I can assign Repair, a reference to the class, to an instance variable but not to a class variable
class NotWorkingDefinitions:
# This will give unresolved reference
a = Repair
class WorkingDefitinions:
def __init__(self):
# This is fine
self.a = Repair
class Repair():
def __init__(self):
whatever = 10
def dosmt(self):
print("staring at a wall")
EDIT: The full answer is given over the different comments. It wasn't about not being able to assign to a class variable. It is just that class variables are immediately resolved and instance variables are not. The latter makes that defining Repair() class after WorkingDefinitions is not an issue.
The above code works if you move Repair to the top. The content of a class is evaluated from top to bottom, so any referenced classes must be defined before actually referencing them.
An example that explores this a bit more in terms of runtime and load-time could be:
# this will not work because the B class is referenced before definition
class A(object):
b_class = B
class B(object):
pass
Alternatively,
# this will work because B is defined first and used later
class B(object):
pass
class A(object):
b_class = B
But both of the examples above do not have a runtime-specific behavior. If instead you wanted A to use B and you had a really good reason to define A first, then you could get away with
class A(object):
def __init__(self):
# bind the B class to each instance of A
self.b_class = B
class B(object):
pass
a = A()
a.b_class
> __main__.B
But the short answer is you must define a variable before using it and when you bind a variable directly to a class (in the class definition, not a method) it must be defined.
The full answer is given over the different comments. It is not about not being able to assign to a class variable. It is that class variables are immediately evaluated and instance variables are not. Instance variables will be evaluated during initiation. The latter makes that defining Repair() class after WorkingDefinitions is not an issue.

Using a class in the same python file

I have two classes in the same file. I am trying to call ClassB from ClassB but receive the following error:
NameError: name 'ClassB' is not defined
class A:
var = B();
class B:
def foo(self):
Class attributes (like A.var that you're trying to define) are evaluated when their class is parsed and created, so B() won't exist when you're trying to reference it in the definition of class A.
Fortunately, you can just add it afterwards and it will have the same effect:
class A:
pass
class B:
def foo(self): pass
A.var = B()
If appropriate, you could also define it as an instance attribute instead:
class A:
def __init__(self):
self.var = B()
class B:
def foo(self): pass
The classes are "seen" in the order in which they are written. Therefore if you have a statement in the first class it will be evaluated directly, on the spot, before going any further in the file.
Your statement var = B() is therefore executed when class B does not exist yet for the Python interpreter.
There are 2 ways to fix this:
define the class B before the class A
OR put the statement var = B() in the constructor of class A as shown below
Your class A will look like this
class A:
def __init__(self):
self.var = B()
This means that the self.var = B will only be evaluated when you create your instance of the class A.
This topic has already been seen several times on Stack Overflow, I would suggest you take a look into one of them in the link below if you have any further questions.
Python class defined in the same file as another class - how do you get access to the one defined later in the file?
I have made a little program on repl.it to show you as an example if you want. It's here.

Unresolved reference in class method

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.

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