Refer to own class in a static method - python

Is there a shorthand for referring to its own class in a static method?
Say I have this piece of code:
class SuperLongClassName(object):
#staticmethod
def sayHi():
print 'Hi'
#staticmethod
def speak():
SuperLongClassName.sayHi() # Is there a shorthand?

Yes, use #classmethod instead of #staticmethod. The whole point of #staticmethod is to remove the extra class parameter if you don't need it.
class SuperLongClassName(object):
#classmethod
def sayHi(cls):
print 'Hi'
#classmethod
def speak(cls):
cls.sayHi()

You probably want a classmethod. It works like a staticmethod, but takes the class as an implicit first argument.
class Claaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaass(object):
#classmethod
def foo(cls):
print cls.__name__
Claaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaass.foo() # prints Claaa...
Warning:
class Subclaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaass(
Claaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaass):
pass
Subclaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaass.foo() # prints Subclaaa...
Alternatively, define a shorter alias for your class at module level:
class Claaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaass2(object):
#staticmethod
def foo():
return _cls2
_cls2 = Claaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaass2
# prints True
print (Claaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaass2 is
Claaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaass2.foo())

Related

How can I dynamically refer to a child class from the super class in Python?

Consider this situation:
class Foo(ABC):
#abstractmethod
def some_method(self):
return
class Bar(Foo):
def some_method(self, param):
# do stuff
return
class Baz(Foo):
def some_method(self, param):
# do stuff differently
return
def do_something_with_obj(some_obj: Foo):
some_param = 'stuff'
some_obj.some_method(some_param)
def main(cond):
if cond:
obj = Bar()
else:
obj = Baz()
do_something_with_obj(obj)
I get an Expected 0 positional arguments error when I try to call some_method() under the do_something_with_obj() method. Of course, this is because I'm essentially calling the abstract method. My question is, how can I dynamically refer to the child class method since I have to choose the right child class based on some condition beforehand?

decorating methods causes method to pass in objects [duplicate]

This question already has answers here:
Python: Bind an Unbound Method?
(5 answers)
Closed 2 years ago.
Problem Description
I want to use a decorator to define a class method, but this requires me to manually give the 'self' object when I shouldn't have to provide that.
def func_wrapper(func):
def call_func(self):
print(self.a)
func()
return call_func
def func():
print('hello')
class test:
def __init__(self, func):
self.a = 0
self.call_func = func_wrapper(func)
mytest = test(func)
#mytest.call_func() #why does this not work?
mytest.call_func(mytest) #this works
I want to be able to mytest.call_func() but this doesn't work, presumably because call_func is bound to the func_wrapper and not mytest. If I manually pass in the object, e.g. mytest.call_func(mytest) this will work, but I don't want to have to manually pass in the object - this creates inconsistent call signatures if one inherited the test class and wrote their own call_func method, because then the method would be properly bound to the class.
Solution Attempts
def func_wrapper2(func, obj):
def call_func():
print(obj.a)
func()
return call_func
class test:
def __init__(self, func):
self.a = 0
self.call_func = func_wrapper2(func, self)
Here is a solution which lets me test.call_func() as desired, but here func_wrapper is not a true decorator as it requires to be passed in the object as well.
Looking on the web I found this blog https://medium.com/#vadimpushtaev/decorator-inside-python-class-1e74d23107f6 which talks about this issue and recommends to define the decorator either in a nested class, or a helper class. However their solution doesn't seem to work and I am getting type errors from passing the wrong number of inputs.
class test2:
class test2helper:
#classmethod
def func_wrapper(func):
print(self.a)
func()
def __init__(self):
self.a = 0
#test2helper.func_wrapper
def call_func(self):
print('hello')
So what is the proper way to use decorators with class methods? Every way to do it seems to cause different issues with how the self is being handled. I am going to use the func_wrapper2 design unless there is a better way to do this.
You are missing one level:
class test2:
class test2helper:
#classmethod
def decorator(cls, func): # this must return a function!
def func_wrapper(self): # ... namely this one, the "wrapper"
print(self.a) # ... where you have access to the instance
func(self) # ... upon which the method is called
return func_wrapper
def __init__(self):
self.a = 0
#test2helper.decorator
def call_func(self):
print('hello')
>>> t = test2()
>>> t.call_func()
0
hello
Or, if you want to go with the earlier attempt without nested class:
def decorator(func): # you are decorating an unbound function!
def func_wrapper(obj):
print(obj.a)
func(obj) # which has to be passed all the arguments
return func_wrapper
class test:
def __init__(self):
self.a = 0
#decorator
def call_func(self):
print('hello')
You can define a class decorator to do what you want:
def class_decorator(cls):
def call_func(self):
print(self.a)
return func()
setattr(cls, 'call_func', call_func)
return cls
def func():
print('hello')
#class_decorator
class Test:
def __init__(self, func):
self.a = 0
mytest = Test(func)
mytest.call_func() # This now works.
Output:
0
hello

Importing class variable python

I have two python classes, one uses the other's variable
class A:
class A(object):
variable = None
#classmethod
def init_variable(cls):
cls.variable = something
class B:
variable = __import__('module').A.variable
class B(object):
#staticmethod
def method():
return variable
I simplified my problem as much as possible. So my question is why I still have B.method() returning NoneType even if I update A.variable class variable with something using init_variable
I changed your code a bit so that it'd actually do what you want:
your_package/klass_A.py
class A(object):
variable = None
#classmethod
def init_variable(cls, something):
cls.variable = something
your_package/klass_B.py
from your_package.klass_A import A
class B(object):
#staticmethod
def method():
return A.variable
Now, you can actually update A.variable and use the updated variable in B as well. For example this:
print B.method()
A.init_variable('123')
print B.method()
returns:
None
123

How do I refer to static class variable in Python?

I have a 'static' class
class A:
a = 1
#staticmethod
def doStuff():
foo(A.a)
Now I need a derived class
class B(A):
a = 2
that basically does
#staticmethod
def doStuff():
foo(B.a)
If A would not be a pseudo static class, I could just derive B from A and
foo(self.a)
would do what I want. Is there a way to avoid copying doStuff() into class B and replace foo(A.a) with foo(B.a)? Something along the line of referring to the class in a 'self' way and having class A s doStuff look like
def doStuff():
foo(class_self.a)
?
I assume you mean class instead of def in your code.
The answer is not to use a staticmethod, but a classmethod. This would behave exactly as you want.
class A:
a = 1
#classmethod
def doStuff(cls):
foo(cls.a)
class B(A):
a = 2

create instance of class within class definition

I'm trying to have a default instance of a class. I want to have
class Foo():
def __init__(self):
....
_default = Foo()
#staticmethod
def get_default():
return _default
However _default = Foo() leads to NameError: name 'Foo' is not defined
Foo does not exist until the class definition is finalized. You can easily refer to it after the class definition, though:
class Foo(object):
def __init__(self):
# ....
Foo.default_instance = Foo()
Note also that I have removed the superfluous getter method in favor of a plain old attribute.
You can also solve the problem with a decorator:
def defaultinstance(Class):
Class.default_instance = Class()
return Class
#defaultinstance
class Foo(object):
# ...
Or, gratuitously, with a metaclass:
def defaultmeta(name, bases, attrs):
Class = type(name, bases, attrs)
Class.default_instance = Class()
return Class
# Python 2.x usage
class Foo(object):
__metaclass__ = defaultmeta
# ...
# Python 3.x usage
class Foo(metaclass=defaultmeta):
# ...
When might you might want to use each method?
Use the post-definition class attribute assignment for one-offs
Use the decorator if you want the same behavior in a lot of unrelated classes and to "hide" the implementation of it (it's not really hidden, or even that complicated, here, though)
Use the metaclass if you want the behavior to be inheritable in which case it's not really gratuitous. :-)
You cannot refer to a class that doesn't yet exist. Within the class definition body, the Foo class is not yet created.
Add the attribute after the class has been created:
class Foo():
def __init__(self):
....
#staticmethod
def get_default():
return Foo._default
Foo._default = Foo()
Note that you also need to alter the get_default() static method; the class body doesn't form a scope, so you cannot reach _default as a non-local from get_default().
You are now, however, repeating yourself a lot. Reduce repetition a little by making get_default() a classmethod instead:
class Foo():
def __init__(self):
....
#classmethod
def get_default(cls):
return cls._default
Foo._default = Foo()
or create the default on first call:
class Foo():
def __init__(self):
....
#classmethod
def get_default(cls):
if not hasattr(cls, '_default'):
cls._default = cls()
return cls._default
You may lazily initialize your default instance.
class Foo(object):
_default = None
#staticmethod
def get_default():
if not Foo._default:
Foo._default = Foo()
return Foo._default

Categories

Resources