How to get a function inside if/else inside an __init__ :
class Foo(object):
def __init__(self, q, **keywords):
if a == "":
print "No empty strings"
else:
def on_g(self, response):
if response.error:
print "Check your internet settings"
else:
self.Bar()
http_client.fetch("http://www.google.com/", self.on_g)
because the program dont read the on_g() if i put an empty string!
If i use the on_g() outside in parallel with __init__() i need a declared variable, for example:
class Foo(object):
def __init__(self, q, **keywords):
if a == "":
print "No empty strings"
else:
self.on_g()
def on_g(self):
print 'hello there'
will return hello there
Your bug is in
http_client.fetch("http://www.google.com/", self.on_g)
which should be
http_client.fetch("http://www.google.com/", on_g)
since you defined a function, not a method.
self (the instance you're creating through __init__ ) doesn't have a on_g method.
Functions for the class-es need to be defined at the class level (as shown on your second chunk of code). They are evaluated when the class is first... erm... "looked-up"? "evaluated"?
That's why your second piece of code works. How come you can call self.on_g within the __init__ when the actual definition of the on_g method seems to come later in the code? It's an odd behavior (at a first glance) for an interpreter, right? Well... That's because when you run self.on_g(), the whole Foo class has already been evaluated and on_g has been added to the class (not to the instance!: To the class)
class Foo(object):
def __init__(self, q, **keywords):
[ . . . ]
else:
self.on_g() # I can use self.on_g() eventhough is defined... _
# |
# |
def on_g(self): # <------------ LATER ---------------------------|
print 'hello there'
Whereas if you define your method within the __init__, the interpreter will yell at you:
class Test(object):
def __init__(self):
def test(self):
print "Hello"
self.test()
a = Test()
Throws:
Traceback (most recent call last):
File "./test.py", line 10, in <module>
a = Test()
File "./test.py", line 8, in __init__
self.test()
AttributeError: 'Test' object has no attribute 'test'
Even if you think Oh, maybe the class doesn't have the test method because it's still within the __init__, and it will have it once the initialization is completed... Meeeck... Wrong:
class Test(object):
def __init__(self):
def test(self):
print "Hello"
a = Test()
a.test()
Same AttributeError.
If you still want to add on_g to the class at runtime (very bad idea, IMHO) you can do the interpreter's job by doing this:
class Test(object):
def __init__(self):
def test(self):
print "Hello"
self.__class__.test = test
self.test()
a = Test()
a.test()
... which correctly prints:
Hello
Hello
Now, the two most straightforward things to do I can think of are:
You move the def on_g(self) to the class level (as you showed in your second code snippet)
You call your http_client.fetch with on_g as a function local to the __init__'s scope (being picky with the language: on_g now is a function, not a method, since is not bound to an object anymore).
def __init__(self, q, **keywords):
if a == "":
print "No empty strings"
else:
def on_g(response):
if response.error:
print "Check your internet settings"
else:
self.Bar()
http_client.fetch("http://www.google.com/", on_g)
Related
class Test():
def __init__(self):
self.__test = "cats"
print(self.__test)
def __example(self):
print("Hello World")
x = Test()
print(x.__dict__)
With the code I wrote above, the print statement will show to access the variable test, I will need to write _Test__test, however as shown I can print the variable if I call it directly afterwards within the __init__ method. So my question is, if I can access it directly after it has been declared by its name i.e self.__test, at which point does it become mangled?
Attributes accessed via .__ are mangled anywhere in the class body (But an inner class declaration would get to it first.).
Think of it as syntactic sugar.
In the context of the Test class body, self.__test is an alias to the mangled name self._Test__test; in context, they mean exactly the same thing.
A demonstration would make this clearer. First, some helper classes.
class PrintAttrAccess:
def __getattr__(self, name):
print(name)
class Empty: pass
Now for the demonstration:
class Test:
print('IN TEST BODY')
(lambda: PrintAttrAccess().__in_lambda)() # Anywhere in the class body works.
classfoo = Empty()
classfoo.__foo = 'foo'
print("Same thing?", classfoo.__foo is classfoo._Test__foo)
print("vars() of classfoo:", vars(classfoo))
class Inner:
print('IN INNER')
PrintAccess().__inner
def __init__(self):
print('IN INIT')
print("Who am I?", self)
self.__test = "cats"
print(self._Test__test) # It's ALREADY MANGLED!
# This line means exactly the same as the one above.
print(self.__test)
localfoo = Empty()
localfoo.__spam = 'spam' # "self" isn't special.
print("vars() of localfoo:", vars(localfoo))
def outside_method(self):
print('OUTSIDE BODY')
print("Who am I?", self)
self.__test = "dogs"
print(self._Test__test)
print(self.__test) # Sugar doesn't apply outside of class body.
Test.outside_method = outside_method # Add a new method to Test class.
Test().outside_method() # init and call as method.
The output is:
IN TEST BODY
_Test__in_lambda
Same thing? True
vars() of classfoo: {'_Test__foo': 'foo'}
IN INNER
_Inner__inner
IN INIT
Who am I? <__main__.Test object at 0x000001CCF3048978>
cats
cats
vars() of localfoo: {'_Test__spam': 'spam'}
OUTSIDE BODY
Who am I? <__main__.Test object at 0x000001CCF3048978>
cats
dogs
If I can access it directly after it has been declared by its name i.e self.__test, at which point does it become mangled?
It becomes mangled when you reference it from outside the class.
Your line 5, print(self.__test) isn't mangled because you're referencing it from inside the class. It's only mangled once you refer to it from outside the class. Thus, you would call
print(x._Test__test)
Note that, you could also use self._Test__test within your class.
class Test():
def __init__(self):
self.__test = "cats"
def get(self):
return self._Test__test
x = Test()
print(x.get()) ## cats
I think this article explains it pretty well: The Meaning of Underscores in Python.
I wonder why my class calls the referenced function (assigned to a static class variable) with with an argument. If I assign the function reference to a normal class variable it works like expected.
Here my example code:
# This function is not editable, because it's imported from an API
def getStuff():
print "I do my stuff!!!"
class foo(object):
GET_STUFF = getStuff
def __init__(self):
print "static var: ",self.GET_STUFF
self.GET_STUFF()
print "outer func: ",getStuff
foo()
This comes up with the following error:
outer func: <function getStuff at 0x0000000003219908>
static var: <bound method foo.getStuff of <__main__.foo object at 0x00000000030AB358>>
Traceback (most recent call last):
File "C:/example.py", line 13, in <module>
foo()
File "C:/example.py", line 10, in __init__
self.GET_STUFF()
TypeError: getStuff() takes no arguments (1 given)
To fix this issue I point the function reference inside the constructor to the class variable:
class foo(object):
def __init__(self):
self.GET_STUFF = getStuff
print "static var: ",self.GET_STUFF
self.GET_STUFF()
The result is like expected and works fine:
outer func: <function getStuff at 0x000000000331F908>
static var: <function getStuff at 0x000000000331F908>
I do my stuff!!!
But:
I wanted to use a static class variable, because it makes it easy to read and simple to setup for different API's. So in the end I would come up with some wrapper classes like in the following:
from API01 import getStuff01
from API02 import getStuff02
# bar calculates stuff object from the API (it calls GET_STUFF)
# and stores the object into self.stuff
import bar
class foo01(bar):
GET_STUFF = getStuff01
def DoSomething(self, volume):
self.stuff.volume = volume
class foo02(bar):
GET_STUFF = getStuff02
def DoSomething(self, volume):
self.stuff.volume = volume
# [...] and so on..
Is there a way to bring it to work in the way I want to setup my wrapper classes, or do I really have to define a constructor for each wrapper class?
Thanks
The reason for the error is that
self.GET_STUFF()
actually means
tmp = getattr(self, 'GET_STUFF')
tmp(self)
That means these two classes are equivalent:
def foo(self): pass
class Foo(object):
a = foo
class Bar(object):
def a(self): pass
In both cases, a function object is added to the class as a member and that means for Python that the function wants self as the first parameter.
To achieve what you want:
from API01 import getStuff01
def wrapper01(self):
getStuff01()
class foo01(object):
GET_STUFF = wrapper01
Just for extend Aaron answer, if you want to have static methods you can use the #staticmethod decorator:
class Calc:
#staticmethod
def sum(x, y):
return x + y
print (Calc.sum(3,4))
>>> 7
I thought already that my object is calling the referenced function with itself as argument. After a bit of research I finally found a solution. When I use a class variable to point to a function it will not referencing a direct pointer. It references the function as a bounced method of it's class. To get rid of the default call of calling a method with getattr, the call function of getattr for the class itself has to be overwritten (in this case the class bar, because foo (the wrapper classes) inherits the functionalities of bar:
import inspect
class bar(object):
GET_STUFF = None
def __getattribute__(self, name):
attr = object.__getattribute__(self,name)
if name == "GET_STUFF":
# Check: is method and is bounced?
if inspect.ismethod(attr) and attr.im_self is not None:
return attr.__func__
return attr
getattr of bar is now pointing to the original function reference, but only for the class variable GET_STUFF, because I want to leave the default functionality for the rest of my variables.
So, when I now execute the following:
class foo(bar):
GET_STUFF = getStuff
def __init__(self):
print "inner func: ",self.GET_STUFF
self.GET_STUFF()
foo()
I get the expected result and can write my wrappers without producing additional code for each module with those wrapper classes:
outer func: <function getStuff at 0x00000000034259E8>
inner func: <function getStuff at 0x00000000034259E8>
I do my stuff!!!
Today I'm viewing another's code, and saw this:
class A(B):
# Omitted bulk of irrelevant code in the class
def __init__(self, uid=None):
self.uid = str(uid)
#classmethod
def get(cls, uid):
o = cls(uid)
# Also Omitted lots of code here
what does this cls() function do here?
If I got some other classes inherit this A class, call it C, when calling this get method, would this o use C class as the caller of cls()?
cls is the constructor function, it will construct class A and call the __init__(self, uid=None) function.
If you enherit it (with C), the cls will hold 'C', (and not A), see AKX answer.
For classmethods, the first parameter is the class through which the class method is invoked with instead of the usual self for instancemethods (which all methods in a class implicitly are unless specified otherwise).
Here's an example -- and for the sake of exercise, I added an exception that checks the identity of the cls parameter.
class Base(object):
#classmethod
def acquire(cls, param):
if cls is Base:
raise Exception("Must be called via subclass :(")
return "this is the result of `acquire`ing a %r with %r" % (cls, param)
class Something(Base):
pass
class AnotherThing(Base):
pass
print Something.acquire("example")
print AnotherThing.acquire("another example")
print Base.acquire("this will crash")
this is the result of `acquire`ing a <class '__main__.Something'> with 'example'
this is the result of `acquire`ing a <class '__main__.AnotherThing'> with 'another example'
Traceback (most recent call last):
File "classmethod.py", line 16, in <module>
print Base.acquire("this will crash")
File "classmethod.py", line 5, in acquire
raise Exception("Must be called via subclass :(")
Exception: Must be called via subclass :(
It's a class factory.
Essentially it the same as calling:
o = A(uid)
cls in def get(...): is A.
I'm attempting to create a dictionary of executable functions within a class. But having trouble getting the self parameter to work correctly.
Consider the following code:
class myclass(object):
def x(self):
return 'x'
def y(self):
return 'y'
EF= {
'a':x,
'b':y,
}
def test(self):
print self.EF['a']()
When I attempt to execute the 'test' function of the class, I get an error around the number of parameters as it evaluates and executes one of the functions in the dictionary.
>>> class myclass(object):
... def x(self):
... return 'x'
... def y(self):
... return 'y'
... EF= {
... 'a':x,
... 'b':y,
... }
... def test(self):
... print self.EF['a']()
...
>>>
>>>
>>> m=myclass()
>>> m.test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in test
TypeError: x() takes exactly 1 argument (0 given)
I've tried a few variations, including this which doesn't work.
EF= {
'a':self.x,
'b':self.y,
}
The only thing that did work was when I explicitly passed self as a parameter, like this.
... def test(self):
... print self.EF['a'](self)
...
>>> m=myclass()
>>> m.test()
x
I've seen other questions about using a dictionary to index functions, but none from within a class.
Here are my questions:
What is the proper way to do handle the self parameter?
I'd prefer to move my dictionary constant outside of the class into my constants section. Can I do that, and if so how? Should I do that?
If I should/have to have my dictionary within my class, why can't I move it to the top of the class?
That's all I got. Thanks for the help.
What is the proper way to do handle the self parameter?
Python uses the self identifier in similar ways to other imperative languages using the this identifier, but it is explicit (as explicit is better than implicit!)
This allows you to use the class as either an instantiated object, or the static class itself.
For an instantiated version, you are probably looking for
>>> class myclass:
def __init__(self):
self.EF = {'a':self.x,'b':self.y}
def x(self):
return 'x'
def y(self):
return 'y'
def test(self):
print self.EF['a']()
>>> my_test_class = myclass()
>>> my_test_class.test()
x
I'd prefer to move my dictionary constant outside of the class into my constants section. Can I do that, and if so how? Should I do that?
If you wanted to use them as static method in a dict outside your class definition, you would need to use the #staticmethod decorator
>>> class myclass(object):
#staticmethod
def x():
return 'x'
#staticmethod
def y():
return 'y'
>>> EF = {'a':myclass.x,'b':myclass.y}
>>> EF['a']()
'x'
If I should/have to have my dictionary within my class, why can't I move it to the top of the class?
Any object attributes should be defined either in the __init__ function, or by explicitly setting them.
Having the dictionary in an init method will make it work
class Myclass(object):
def x(self):
return 'x'
def y(self):
return 'y'
def __init__(self):
self.EF= {
'a':self.x,
'b':self.y
}
def test(self):
print self.EF['a']()
m=Myclass()
m.test()
In reference to your questions. The class is kind of a dictionary or named tuple of attributes and executable functions. The functions themselves only define behavior. self is a sack of state related to your instance. if you save a pointer to that function somewhere else and provide it with a given self that is an instance of your class it should work as normal.
class MyClass(object):
def __init__(self, x):
self.x = x
def fun(self):
return self.x
i = MyClass(1)
print i.fun()
f = MyClass.fun
i2 = MyClass(2)
print f(i2)
When you call using the standard i.fun() all it's doing is passing i in implicitly as the selfargument.
I'd like to store some information about a class as class (static) variables. However, I can't figure out how these things get initialized. Here is a basic, dumb example:
class A(object):
clsVar = 'a'
#classmethod
def clsMeth(cls):
print 'changing clsVar'
cls.clsVar = 'b'
A.clsMeth()
# prints 'changing clsVar'
print A.clsVar # prints 'a'
A.clsVar = 'b'
print A.clsVar # prints 'b'
Since the function got called (as the print statement worked), why didn't the class variable stay changed? Do I have to use a metaclass if I don't want to do it after the class definition completes?
[Specifically, I want clsMeth to be a decorator and have the class variable be a list of all the functions that were so decorated. I'm guessing this isn't the right way to go about accomplishing that, so I've moved on, but I'm still curious.]
EDIT: As numerous people have pointed out, the code above won't run. I was running it in an IPython session where the call to A.clsMeth() would refer to a previous version of A and run. Such are the risks of using an interpreted language, I guess. I ended up going with something like this:
outsideDict = {}
def outsideDec(func):
outsideDict[func.__name__] = func
class A(object):
#outsideDec
def someMethod(self):
print 'ID %s' % id(self)
def otherMethod(self):
print 'other'
print outsideDict
one, two = A(), A()
outsideDict['someMethod'](one)
outsideDict['someMethod'](two)
Perhaps this should be another question, but when outsideDec gets run, is there a way to tell what class it's argument is a member of? Or is there a better way of doing introspection like this in Python? I recognize I'm veering off course here so I'll accept the answer below and do more research. Thanks everyone!
The call to A.clsMeth() in the definition of A will not run, as A does not exist at that point:
>>> class A(object):
... clsVar = 'a'
... #classmethod
... def clsMeth(cls):
... print 'changing clsVar'
... cls.clsVar = 'b'
... A.clsMeth()
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in A
NameError: name 'A' is not defined
The code may have seemed to work if A had been defined previously (eg, if you were testing it out in the REPL), but the call to A.clsMeth would have been called on the old class, which would be shadowed by the new one.
However, we can definitely put that call after the definition and get the result you want:
>>> class A(object):
... clsVar = 'a'
... #classmethod
... def clsMeth(cls):
... print 'changing clsVar'
... cls.clsVar = 'b'
...
>>> A.clsMeth()
changing clsVar
>>> A.clsVar
'b'
Of course, as fabianhrj noted, you can put it in the constructor as well, but it won't be called until you create an instance.