This Question / Answer (Python call constructor in a member function) says it is possible to to call the constructor from within a member function.
How do I do that?
Is it good a style?
I tried it with the following code:
class SomeClass(object):
def __init__(self, field):
self.field = field
def build_new(self):
self = SomeClass(True)
def main():
inst = SomeClass(False)
inst.build_new()
print(inst.field)
if __name__ == '__main__':
main()
As output I get: False
Since I called the build_new() method inst.field should be True or not?
The problem is not in calling the constructor, but what you're doing with the result. self is just a local variable: assigning to it won't change anything at all about the current instance, it will just rebind the name to point to a new instance which is then discarded at the end of the method.
I'm not totally certain what you are trying to do, but perhaps you want a classmethod?
class SomeClass(object):
...
#classmethod
def build_new(cls):
return cls(True)
SomeClass.build_new(False)
I believe what you are looking for is just calling the init function again.
class SomeClass(object):
def __init__(self, field):
self.field = field
def build_new(self):
self.__init__(True)
This will cause the field variable to be set to True over False. Basically, you are re-initializing the instance rather than creating a brand new one.
Your current code creates a new instance and just loses the reference to it when it goes out of scope (i.e. the function returning) because you are just rebinding the name of self to a different value not actually changing the inner contents of self.
Related
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.
class Deco:
def __init__(self, name):
self.name = name
def __call__(self, test_class):
def inner_func(whatisit):
return whatisit
test_class.method = inner_func
return test_class
class TestClass:
def __init__(self, name):
self.name = name
#Deco('deco')
class TestClassWrapped:
def __init__(self, name):
self.name = name
test = TestClass('test')
test = Deco('deco')(test)
test_wrapped = TestClassWrapped('test')
print(test.method('whatisit')) >> whatisist
print(test_wrapped == test_wrapped.method()) >> True
Why do test.method and test_wrapped.method return different results ?
It seems that the first argument in test_wrapped.method is self, while it isn't for test.method. Why does it differ from one to the other?
The difference isn't how the decoration works, but how calling works. When an instance calls a method defined on its class, as test_wrapped does, it always passes self as the first argument. Meanwhile, when an object calls an attribute of itself that happens to be a function, but doesn't exist on its class, it calls it without passing self. Consider this simple class:
class LoudTalker:
def __init__(self, name):
self.shout_hello = lambda: print("HELLO, I'M {}".format(name.upper()))
>>> john = LoudTalker("John")
>>> LoudTalker.shout_hello()
HELLO, I'M JOHN
Note that john did not pass self to shout_hello (which would have thrown the error <lambda>() takes 0 positional arguments but 1 was given) because shout_hello was defined directly on the instance, not on the class.
Walking through your code step-by-step:
You create a regular TestClass named test.
You manually call Deco and provide it with test, with the line test = Deco('deco')(test).
This makes your code go through the __call__ function, which modifies the passed class test to set its method attribute to the nested function. It then returns it, and so test now contains a successfully modified TestClass : calling test.method('whatisit') will successfully return 'whatisit'. Importantly, you're NOT accessing a method here : you're accessing a FUNCTION through an ATTRIBUTE. self is passed to every method of classes in Python, but since this isn't a method, it doesn't come into play here. Try printing type(test.method), you'll see <class 'function'> and not <class 'method'>. Importantly, you've passed an INSTANCE of a TestClass, not the class definition itself : and only this instance named test has had its method attribute set.
You then create a TestClassWrapped named test_wrapped. Upon creating it, it enters the __call__ once more, passing it TestWrappedClass as the test_class parameter. Importantly, you've passed a DEFINITION of the TestWrappedClass, not an instance of it. Setting method here will modify it for every instance of TestWrappedClass you'll later create, and can even be accessed without instantiating anything. Try calling TestClassWrapped.method("abc") : it will print abc without instantiating a TestClassWrapped at all. Interestingly, when set in this way, it's not set as an attribute but as a method! Try printing type(test_wrapped.method). This is what I believe to be the source of confusion.
In the case of print(test_wrapped.method()), you have to remember that every method of instantiated classes take self as their first parameter. This means that test_wrapped.method() will return self : hence why test_wrapped == test_wrapped.method(). Note that this doesn't apply to methods called from a class definition, like I've shown earlier. TestClassWrapped.method("abc") HAS to take a parameter of some sort (like abc), else it will complain it's lacking an argument.
So this is why test.method('whatisit') returns 'whatisit' and doesn't take self as parameter, and why test_wrapped.method() does return self.
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.
class AndTrigger(Trigger):
def __init__(self,object1,object2):
self.object1 = object1
self.object2 = object2
def evaluate(self,object):
return self.object1.evaluate(self) and self.object2.evaluate(self)
I implemented this AND trigger and it works as it is supposed to, but I was only able to make it work by trial and error--I have no idea what 'self' is doing in this class.
Here's what I think is going on: the __init__ is the constructor for the class, so any instance of the class uses this when created. The class has two attributes (object1, object2), the __init__ when the class is created tells the new instance that these new attributes will be called 'object1' and 'object2' so they are assigned to self.object1 etc.
Now, this evaluate function is supposed to prevent a raise notimplemented in Trigger, but that's not what I don't get. In this evaluate function, it looks like it has two arguments--the instance of AndTrigger and another object. But where is this other object in the definition of evaluate()? It's just a puzzle to me how this works, but it does!
When you're calling a bound member function, the first argument (self) is supplied automatically. It refers to the object on which the function is invoked.
Let's for the sake of illustration assume that both self.object1 and self.object2 are of type TriggerX. The following:
def evaluate(self, obj):
return self.object1.evaluate(self) and self.object2.evaluate(self)
is then equivalent to:
def evaluate(self, obj):
return TriggerX.evaluate(self.object1, self) and TriggerX.evaluate(self.object2, self)
I hope this clears things up.
P.S. I suspect from the context that the following:
def evaluate(self, obj):
return self.object1.evaluate(self) and self.object2.evaluate(self)
should be
def evaluate(self, obj):
return self.object1.evaluate(obj) and self.object2.evaluate(obj)
P.P.S. Please don't use object as a variable name, since this shadows a built-in class.
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