class DockerEngine(Device):
def __init__(self):
super(DockerInfo, self).__init__()
self.docker_id = None
self.host_ip_address = None
self.total_containers = 0
self.running_containers = 0
self.paused_containers = 0
self.stopped_containers = 0
#property
def host_ip_address(self):
return self._host_ip_address
#host_ip_address.setter
def host_it_address(self, ip):
self._host_ip_address = ip
#property
def docker_id(self):
return self._docker_id
#docker_id.setter
def docker_id(self, id):
self._docker_id = id
When I initialize a DockerEngine object, it complains that in __init__ self.host_ip_address, can't set attribute.
Your code has a typo
Change host_it_address to host_ip_address.
#host_ip_address.setter
def host_it_address(self, ip): <--- WRONG FUNCTION NAME
self._host_ip_address = ip
Related
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)
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
Is it possible to have a class attribute targeting another attribute from the same object and have a function to update the value of the target?
class MyObject(object):
def __init__(self):
self.var_1 = 1
self.var_2 = 2
self.var_3 = 3
self.current_var = self.var_1
def update_var(self, value):
self.current_var = ...
Expected outcome:
>>> x = MyObject()
>>> x.update_var(10)
>>> x.var_1
10
>>> x.current_var = x.var_2
>>> x.update_var(5)
>>> x.var_2
5
You can use the __dict__ of the object or as said by #bla setattr,
And Enum so you don't use string to specify the attribute:
from enum import Enum
class MyObject(object):
def __init__(self):
self.var_1 = 1
self.var_2 = 2
self.var_3 = 3
self.current_var = None
def update_var(self, value):
if self.current_var is None:
raise Exception('Current var is not set')
self.__dict__[self.current_var.name] = value
setattr(self, self.current_var.name, value) # Same result
m = MyObject()
attrs = vars(m)
attrs_enum = Enum("attrs_enum", attrs)
m.var_1 # 1
m.current_var = attrs_enum.var_1
m.update_var(10)
m.var_1 # 10
m.current_var = attrs_enum.var_2
m.var_2 # 2
m.update_var(20)
m.var_2 # 20
I don't like using a string to specify the attribute, but this is solution
I suggest making current_var a property that acts as a proxy for a given instance attribute. You can use set_current_var to update the proxy target.
Code
class MyObject(object):
current_var = 1
def __init__(self):
self.var_1 = 1
self.var_2 = 2
self.var_3 = 3
def set_current_var(self, name):
self._current_var = name
#property
def current_var(self):
return getattr(self, self._current_var)
#current_var.setter
def current_var(self, value):
setattr(self, self._current_var, value)
Example
x = MyObject()
print(x.var_1) # 1
x.set_current_var('var_1')
print(x.current_var) # 1
x.current_var = 4
print(x.var_1) # 4
You can create a wrapper class for your MyObject attribute values. That way, a reference will exist from the contents of current_var to the attribute bound in __dict__:
class _int:
def __init__(self, _val):
self.value = _val
def __repr__(self):
return str(self.value)
class MyObject(object):
def __init__(self):
self.var_1 = _int(1)
self.var_2 = _int(2)
self.var_3 = _int(3)
self.current_var = self.var_1
def update_var(self, value):
self.current_var.value = value
x = MyObject()
x.update_var(10)
print(x.var_1)
x.current_var = x.var_2
x.update_var(5)
print(x.var_2)
Output:
10
5
whenever i print the c1 object, it prints:
<main.Car object at 0x7fde8b29a240>
however i added the str method, to format it to a proper string, why is it not printing a readable string?
import copy
class Prototype:
def __init__(self):
# constructor method to create the object
self._objects = {}
def register_object(self, name, obj):
# this method is used to register an object
self._objects[name] = obj
def unregister_object(self, name):
# this method is used to unregister an object
del self._objects[name]
def clone(self, name, **attr):
obj = copy.deepcopy(self._objects.get(name))
obj.__dict__.update(attr)
return obj
class Car:
def __init__(self):
self.name = "Skylark"
self.color = "blue"
self.options = "extra horsepower in engine"
def __str__(self):
return '{} | {} | {}'.format(self.name, self.color, self.options)
c = Car()
prototype = Prototype()
prototype.register_object('skylark',c)
c1 = prototype.clone('skylark')
print(c1)
There is a problem with the indentation in your code. I've corrected this and can get the desired answer too. The indentation is a bit off for the function defs. in both the classes.
I've called this file as test.py
import copy
class Prototype:
def __init__(self):
# constructor method to create the object
self._objects = {}
def register_object(self, name, obj):
# this method is used to register an object
self._objects[name] = obj
def unregister_object(self, name):
# this method is used to unregister an object
del self._objects[name]
def clone(self, name, **attr):
obj = copy.deepcopy(self._objects.get(name))
obj.__dict__.update(attr)
return obj
class Car:
def __init__(self):
self.name = "Skylark"
self.color = "blue"
self.options = "extra horsepower in engine"
def __str__(self):
return '{} | {} | {}'.format(self.name, self.color, self.options)
c = Car()
prototype = Prototype()
prototype.register_object('skylark',c)
c1 = prototype.clone('skylark')
print(c1)
When I run the file
$ python test.py
The output is:
#Output: Skylark | blue | extra horsepower in engine
I am trying to initialize a list in a class like this:
class Node():
def __init__(self):
self.info = None
self.word = ''
for i in range(256):
self.ptrs[0] = None
if __name__ == '__main__':
n = Node()
Now this throws an error
self.ptrs[0] = None
AttributeError: Node instance has no attribute 'ptrs'
I am sure that I'm missing something stupid. What is it?
I think you want this:
class Node():
def __init__(self):
self.info = None
self.word = ''
self.ptrs = [None]*256