Python: get value of property - python

I have this Python 2 code:
class VKHandshakeChecker:
def __getAnswers(self):
return self.__answers
def __getStatus(self):
return self.__status
def __init__(self,vkapi,maxDepth=6):
isinstance(vkapi,VKApi.VKApi)
self.vkapi = vkapi
self.__maxDepth=maxDepth
self.__answers = list()
self.__status = 'IDLE'
self.status = property(VKHandshakeChecker.__getStatus)
self.answers = property(VKHandshakeChecker.__getAnswers)
I want to get answers property. But when I execute this code:
checker = VKHandshakeChecker.VKHandshakeChecker(api)
print(checker.status)
I get <property object at 0x02B55450>, not IDLE. Why?

You can't put descriptors (like a property object) on the instance. You have to use them on the class.
Simply use property as a decorator:
class VKHandshakeChecker:
#property
def answers(self):
return self.__answers
#property
def status(self):
return self.__status
def __init__(self,vkapi,maxDepth=6):
self.vkapi = vkapi
self.__maxDepth=maxDepth
self.__answers = list()
self.__status = 'IDLE'
I removed the isinstance() expression, it doesn't do anything as you are ignoring the return value of the function call.

Related

Parameter self unfilled, but when I fill it it gives expected type ' ' but got 'Type[]' warning

class Player:
def __init__(self):
self.godHole = GodHole
self.pits = []
for i in range(0, 6):
self.pits.append(Pit())
def return_stones(self):
return self.godHole.return_stones(self.godHole)
#or return self.godHole.return_stones()
# same warning for invoking seld.godHole.increment_stones()
class GodHole:
def __init__(self):
self.stones = 0
def return_stones(self):
return self.stones
def change_stones(self, s):
self.stones = s
def increment_stones(self):
self.stones += 1
When using the commented line I get self unfilled warning. when I used the first one I get the expected type ' ' but got 'Type[]' warning
What am I doing wrong? How can I fill self parameter? Can I even access instance attributes this way?
The attribute godHole of class Player, it is just a class, and no instantiation operation is performed, you directly use the instance method return_stones below, and pass in the class GodHole, which is wrong.
There are two ways to execute instance methods:
call directly using the class instance
when a class uses an instance method, the instance is passed in as a parameter
class Player:
def __init__(self):
self.godHole = GodHole()
self.pits = []
for i in range(0, 6):
self.pits.append(Pit())
def return_stones(self):
return self.godHole.return_stones()
or
class Player:
def __init__(self):
self.godHole = GodHole
self.pits = []
for i in range(0, 6):
self.pits.append(Pit())
# def return_stones(self):
# return self.godHole.return_stones(self.godHole())
def return_stones(self, obj: GodHole):
# obj is an instance object of class GodHole
return self.godHole.return_stones(obj)

Python Classes Understand methods

I have simple task: we have class TestingClass and we wanna simply test his methods. And we have class TestHelper for testing purpose.
class TestingClass():
def testing_method_1(self):
return False
def testing_method_2(self):
return True
class TestHelper():
def __init__(self, class_name):
pass
def add(self, func_name, func_result):
pass
def run(self):
pass
helper = TestHelper(TestingClass)
helper.add(“testing_method_1”, False)
helper.add(“testing_method_2”, True)
result = helper.run()
my target implement methods for class TestHelper . I solved it for myself but I think its bad realization. I initialize empty dictionary and test class. Next I add every method and test method result to dictionary. In run method I compare results.
class TestHelper():
def __init__(self, class_name):
self.test_class = class_name()
self.func_list = {}
def add(self, func_name, func_result):
temp = 'self.test_class.' + func_name
self.func_list[temp] = func_result
def run(self):
for f in self.func_list.keys():
if eval(f)() == self.func_list[f]:
print('yes')
else:
print('no')
Can I resolve it in best way? Thanks!
Using eval for this purpose is overkill.
You could instead use the getattr() function to retrieve the function and call it.
Read more: Python Docs
class TestHelper():
def __init__(self, class_name):
self.test_class = class_name()
self.func_list = {}
def add(self, func_name, func_result):
# { <function>:<desired result> }
self.func_list[func_name] = func_result
def run(self):
for func, desired_result in self.func_list.items():
if getattr(self.test_class, func)() is desired_result:
print('yes')
else:
print('no')
This code produces results:
...
>>> helper = TestHelper(TestingClass)
>>> helper.add("testing_method_1", False)
>>> helper.add("testing_method_2", True)
>>> result = helper.run()
yes
yes
Of course you should also test if the class even has an attribute with the given function name. You can use hasattr() for this.

How to have the same updated value of a Parent class be passed down to a inner class?

I need to access the value of an attribute defined at the parent class inside an inner class, here's the code:
class main(object):
def __init__(self):
self.session_id = None
self.devices = self.Devices(self.session_id)
class Devices(object):
def __init__(self, session_id):
self.session_id = session_id
And here's how I would like to use it:
>>> m = main()
>>> m.session_id = 1
>>> m.session_id
1
>>> m.devices.session_id
>>>
My expectation is that m.devices.session_id will always have the exact same value as m.session_id. I understand that at this point when I instantiate the inner class the session_id value is passed down as None because that's how it was initiated but I'm not sure how I can keep both values the same without doing something very ugly like:
m.devices.session_id = m.session_id
outside the class code.
How can I accomplish that inside the class itself ?
The other answer works, but I think this is a better design: lose the nested class, and add a getter on the device object to lookup a backref:
class Main(object):
def __init__(self):
self.session_id = None
self.devices = Devices(main_obj=self)
class Devices(object):
def __init__(self, main_obj):
self.main_obj = main_obj
...
#property
def session_id(self):
return self.main_obj.session_id
The difference here is that you're not storing the same data twice, so they can not get out of sync - there is only one "source of truth" for the session_id (on main object).
In the earlier answer, the data is actually stored in two different namespaces and will get out of sync as easily as m.devices.session_id = 123.
You can do it like this:
class main(object):
def __init__(self):
self._session_id = None
self.devices = self.Devices(self._session_id)
#property
def session_id(self):
return self._session_id
#session_id.setter
def session_id(self, value):
self._session_id = self.devices.session_id = value
class Devices(object):
def __init__(self, session_id):
self.session_id = session_id

how can i reference to an object variable without passing it as parameter in python classes

I am try to reference an object variable inside the class without passing it in parameters but it is throwing error
class Sample:
def __init__(self):
v = []
v.append(name)
v.append(email)
s = Sample()
s.name = "xxxx"
s.email = "ss#ss.com"
print s.v
error:
NameError: global name 'name' is not defined
I am assigning the variable name in the object now how can i call it inside the class without adding parameters to function
if you absolutely must avoid attributes:
class Sample:
def __init__(self):
self.v = []
def addName(self, name):
self.v.append(name)
def addEmail(self, email):
self.v.append(email)
s = Sample()
s.addName("xxxx")
s.addEmail("abc#def.com")
print(s.v)
Yet another way to do this is to use decorators and #property:
class Sample(object):
def __init__(self):
self.v = [None, None]
#property
def name(self):
return self.v[0]
#property
def email(self):
return self.v[1]
#name.setter
def name(self, value):
self.v[0] = value
#email.setter
def email(self, value):
self.v[1] = value
s = Sample()
s.name = "xxxx"
s.email = "ss#ss.com"
print s.v
Notes:
Your class must be extending object explicitly in python 2 for this to work
#property decorated methods are working as "getters" and return a value
#<name>.setter is a setter method responsible for setting <name> member, so #email.setter sets the email and is being invoked when x.email = ... is called
The above may be a bit long-winded but allows for a clean API which hides the details from the user... Some people do prefer to add get/set_name methods to be more explicit but the above is more pythonic
If your requirements are dynamic, you can create attributes at run time like,
class Sample:
pass
s = Sample()
setattr(s,"name","chanda")
setattr(s,"email","xyz#gmail.com")
setattr(s,"v",[s.name,s.email])
print(s.name) #chanda
print(s.email) #xyz#gmail.com
print(s.v) #['chanda', 'xyz#gmail.com']
print(s.__dict__) #{'email': 'xyz#gmail.com', 'v': ['chanda', 'xyz#gmail.com'], 'name': 'chanda'}

Passing values to class

I have this abstract class in Python:
class TransactionIdsGenerator(object):
def getId(self):
raise NotImplementedError
And this class that implements:
class TransactionIdsGeneratorGeneric(TransactionIdsGenerator):
INI_FILE = '/platpy/inifiles/postgres_config.ini'
__dbManager = None
def __init__(self):
TransactionIdsGenerator.__init__(self)
def getId(self):
_ret = None
_oDbManager = self.__getDbManager()
if _oDbManager.execQuery("select nextval('send_99_seq');"):
_row = _oDbManager.fetchOne()
if _row is not None:
_ret = _row[0]
return _ret
def __getDbManager(self):
if self.__dbManager is None:
self.__dbManager = PostgresManager(iniFile=self.INI_FILE)
return self.__dbManager
And in other file i have the instance of the class:
def __getTransactionIdsGenerator(self, operatorId):
_ret = TransactionIdsGeneratorGeneric()
return _ret
Is some way to pass the varibale operatorId to the instance, so i can use in the method getId in the class?
Thanks!
You just need to pass it as an argument to __init__. (Note that in your current code, you don't even need to define TransactionIdsGeneratorGeneric.__init__, since the only thing it does is call the parent's __init__.)
class TransactionIdsGeneratorGeneric(TransactionIdsGenerator):
INI_FILE = '/platpy/inifiles/postgres_config.ini'
__dbManager = None
def __init__(self, opid):
TransactionIdsGenerator.__init__(self)
self.opid = opid
Then when you instantiate the class:
def __getTransactionIdsGenerator(self, operatorId):
_ret = TransactionIdsGeneratorGeneric(operatorId)
return _ret
The key is that the child class's __init__ doesn't need to have the exact same signature as the parent's, as long as you make sure the correct arguments are passed to the parent when you call it. This isn't entirely true if you are making use of super, but since you aren't, I'll ignore that issue. :)

Categories