Please help to understand how to correctly use decorators in classes. For example, I want to check variables before executing the class, and if it's exist run class with this variable. How to do this?
My not working example :
import os,sys
import requests
def checkCredentials(function):
KEY = os.environ['KEY']
if KEY:
print("exist")
return KEY
else:
print("nope")
sys.exit(0)
@checkCredentials
class StartUp(object):
def __init__(self, argument1):
self.argument1 = argument1
def printstr(self):
print(self.argument1)
if __name__ == '__main__':
start = StartUp()
My error :
python3.6 ./main.py
exist
Traceback (most recent call last):
File "./main.py", line 26, in <module>
start = StartUp()
TypeError: 'str' object is not callable
You should read up some more on decorators, maybe check PEP 3129 or PEP 318. The following example from the former PEP illustrates the semantics of class decorators:
# Solution 1: Without class decorators
class A:
pass
A = foo(bar(A))
# Solution 2: With class decorators
@foo
@bar
class A:
pass
The two solutions produce identical results. In Solution 1
the functions foo
and bar
are called explicitly to modify the initial class A
and produce a modified variant. By using decorators, the same effect can be achieved much more clearly: this is Solution 2
.
Let's apply this to your code example. Your final line of code is
start = StartUp()
which translates to
start = checkCredentials(StartUp)()
However, checkCredentials
either returns nothing or a str
, hence the TypeError
. I am not sure what exactly you want to achieve with the decorator. If all you want is a test for the presence of the specific environment variable, the following decorator might produce the desired effect:
def checkCredentials(cls):
KEY = os.environ['KEY']
if KEY:
print("exist")
return cls
else:
print("nope")
sys.exit(0)
Note that this returns the original class from the decorator iff the environment variable is set (happy code-path) and terminates execution otherwise (hence there's no need to return anything form the decorator).