Assume I have a class CLASS and I create a methodfnc in it
class CLASS():
def __init__(self,arg):
#initizalize
self.arg = arg
def fnc(self):
print(self.arg)
if I (in my class) wants to call fnc in a method prnt I can do it in two different ways, one using self.fnc and one just using fnc
class CLASS():
def __init__(self,arg):
#initizalize
self.arg = arg
def fnc(self):
print(self.arg)
def prnt(self):
self.fnc() #Method one
fnc() #Method two
which both seems to be working. I do know the self argument and how it works, but I do not understand the difference of the two method/function calls.
This should not work. It works because CLASS in your code is not actually a class since you used keyword def instead of class to define it.
What you actually did is define a function CLASS, which when executed defines some other functions.
To correct this declare your class like this:
class CLASS:
And your second call will raise a NameError probably because fnc does not exist in the scope of your method.
Related
So, I have a situation as described as follow:
class A(object):
def __init__(self):
pass
def foo(self):
a = self.InnerClass()
a.hooo()
class InnerClass(object):
def hooo(self):
print 'Yeah!'
class DummyA(A):
class InnerClass(A.InnerClass):
def hooo(self):
print 'Yay!'
class Test(object):
x = DummyA()
x.foo()
A is my main class which I want to test. Then there is an inner class whose function hooo() is getting called. I want to override that function in my DummyA class. so, I did that as described in code. It works and the output is 'Yay!'. I have seen in many examples online that outer class always accesses inner class by this syntax. OuterClass.InnerClass but in my case I have used self to access inner class. Is it bad practice? if so, for what reason? Any other way I can test the function hooo?
Consider the following snippet in Python:
class A:
def f(self, arg):
print(self, arg)
class B(A):
#classmethod
def f(cls, arg):
super(B, cls).f(arg)
print(cls, arg)
B.f(1)
I know it's wrong to write like this, but I'm trying to understand what's going on behind the scenes. Why do I need to pass the first argument explicitly in call to inherited function? If this snippet is run, I get an exception that the required positional argument was not provided.
When I call B.f(1), the first argument (the class B) is passed implicitly. I thought the same should be the case when I call the inherited ordinary method through class instance: self should be class B.
Is it some interpreter magic - say, it looks at class A, sees that f is ordinary function there, and does not set the first argument implicitly because it's called as class method?
I ran the code successfully by simply changing
super (B, cls).f(arg)
to:
super (B, cls).f (cls, arg)
and it worked fine. I guess the class isn't passed implicitly.
class A(object):
def wrapped(self, func):
func.string = self.get_something()
return func
def get_something(self):
return "something"
#wrapped
def main(self):
print self.main.string
a = A()
a.main()
TypeError: wrapped() takes exactly 2 arguments (1 given)
wrapped() is called at the definition of main(). When it is called, it is not given self, because there is no instance of A that can be given to wrapped(). To do what you want, don't use decorators. Instead, define an __init__() method that assigns the right attributes. I don't know why you want it to be an attribute of self.main(), however. Generally it is not a good idea to add attributes to functions. You already have a class; use it. Just define self.string instead of self.main.string.
How can I pass an object as an argument to a class method and call the method of the passed object when the class method is called?
Say I have:
class myclass:
def __init__(self):
pass
def myfunc(self, something):
something.do()
anobject = blah.xyz()
another_obj = myclass()
another_obj.myfunc(anobject)
So long as something has a .do method, that should work as given (once you fix your indentation and order of declaration). Have you tried running it?
This is (more or less) how a lot of standard functions work - for example, the built-in len function is pretty much
def len(obj):
return obj.__len__()
Which method of the past object do you want to call?
By the way, myfunc is an instance method.
class student :
ID=0
name=""
def fun(s=student()):
print (s.id)
print (s.name)
st=student()
fun(st)
I have decorator #login_testuser applied to method test_1():
class TestCase(object):
#login_testuser
def test_1(self):
print "test_1()"
Is there a way I can apply #login_testuser on every method of the class prefixed with "test_"?
In other words, the decorator would apply to test_1(), test_2() methods below, but not on setUp().
class TestCase(object):
def setUp(self):
pass
def test_1(self):
print "test_1()"
def test_2(self):
print "test_2()"
In Python 2.6, a class decorator is definitely the way to go. e.g., here's a pretty general one for these kind of tasks:
import inspect
def decallmethods(decorator, prefix='test_'):
def dectheclass(cls):
for name, m in inspect.getmembers(cls, inspect.isfunction):
if name.startswith(prefix):
setattr(cls, name, decorator(m))
return cls
return dectheclass
#decallmethods(login_testuser)
class TestCase(object):
def setUp(self):
pass
def test_1(self):
print("test_1()")
def test_2(self):
print("test_2()")
will get you what you desire. In Python 2.5 or worse, the #decallmethods syntax doesn't work for class decoration, but with otherwise exactly the same code you can replace it with the following statement right after the end of the class TestCase statement:
TestCase = decallmethods(login_testuser)(TestCase)
Sure. Iterate all attributes of the class. Check each one for being a method and if the name starts with "test_". Then replace it with the function returned from your decorator
Something like:
from inspect import ismethod, getmembers
for name, obj in getmembers(TestCase, ismethod):
if name.startswith("test_"):
setattr(TestCase, name, login_testuser(obj))
Are you sure you wouldn't be better off by putting login_testuser's code into setUp instead? That's what setUp is for: it's run before every test method.
Yes, you can loop over the class's dir/__dict__ or have a metaclass that does so, identifying if the attributes start with "test". However, this will create less straightforward, explicit code than writing the decorator explicitly.