How do I re-initialize the base class using self.__init__?
In the following example my goal is to inherit eComm which is a socket derived driver. This handles connect/disconnect. If it disconnects we need to reinitialize it using __init__, however it appears to refer to the comDriver when self.__init__ is called.
How do I properly initialize the superclass to allow for this?
(else: self.__init__ in connect() is referring to comDriver, not eComm like it should)
The following is a simple case to reproduce the error in Python 3.x
class eComm():
def __init__(self):
self.s = "example object"
self.initialized = True
self.connected = False
def connect(self, IP_ADDRESS, PORT):
if self.initialized:
print(IP_ADDRESS, PORT)
else:
print("REINITIALIZING")
self.__init__()
self.connected = True
return(True)
class comDriver(eComm):
def __init__(self, IP_ADDRESS, PORT):
self.IP = IP_ADDRESS
self.PORT = PORT
super().__init__()
pass
def getTemp(self):
print("EXAMPLE FUNCTION")
return(1)
x = comDriver("192", 7)
x.connect("161", 6)
x.initialized = False
x.connect("111", 5)
IMO you're using the special method __init__ wrongly. It's meant to initialize a Python object, not anything outside that scope.
With your intention, I recommend that you create a separate initializer function, and call it from __init__. Here's an example:
class eComm():
def __init__(self):
self.initialize_eComm()
def initialize_eComm(self):
self.s = "example object"
self.initialized = True
self.connected = False
And then you can replace self.__init__() with self.initialize_eComm() to avoid name conflict in subclasses.
self.__init__ in connect() is referring to comDriver, not eComm like it should
This doesn't quite hold -- self refers to the calling object, which is comDriver. If you want to call to the __init__ method on eComm regardless of what classes extend it, you will have to reference in explicitly.
eComm.__init__(self)
But, the other answers and comments are right that this is not a good use of __init__.
Related
This question already has an answer here:
How to access outer attribute class within inner class?
(1 answer)
Closed 3 years ago.
As a title, I have a versatility function in parent class that will share use in child class A.k.A inner class. In below, I need to pass outer_send function from parent class. then, use it with call inner_send function inside Identify class alias child class. The result will output Test.
class Device:
def __init__(self):
self.identify = self.Identify(self.outer_send())
def outer_send(message):
print(message)
def last_error(self):
return self.identify.error_info
class Identify:
def __init__(self, send):
self.inner_send() = send()
def set_error(self, error):
self.error_info = error
device = Device()
device.identify.inner_send('test')
I don't like the pattern and I would recommend designing it differently. However, this does what I think you want to do:
class Device:
def __init__(self):
self.identify = self.Identify(self._send)
def _send(self, message):
print(message)
class Identify:
def __init__(self, _send):
self.send = _send
device = Device()
device.identify.send('test')
A few notes: I renamed outer_send to _send, as I assume you don't want people calling that directly on the Device object - if you do, just rename it send and it still works; the error bit seemed superfluous, so left it out; your outer_send was missing self as a parameter - it doesn't need it, but if you do want to leave it out, annotate the method with #staticmethod to avoid warnings.
I have 3 classes defined this way:
class Device:
Some method
class SSH:
def connect(self,type):
# code
def execute(self,cmd):
# code
class Netconf:
def connect(self,type):
# code
def execute(self,cmd):
# code
Note SSH and Netconf classes have same method names but they do things differently.
I have an instance of class Device and would like to access methods like this-
d = Device()
d.connect('cli') # <-- This should call SSH method and subsequently
# d.execute(cmd) should call execute method from SSH class
# too.
d.connect('netconf') # <-- This should call Netconf method and subsequently
# d.execute(cmd) should call execute method from
# Netconf class too.
The question is - how do I make it happen? I want to be able to use methods of SSH/Netconf class on Device class instance 'd' based on the input.
You can do this by storing the type of device connected in a private Device attribute and then forwarding most method calls to it by adding a custom __getattr__() method. This is a little tricky in the connect() method because that's were the target device is defined (as opposed to in the Device.__init__() initializer).
I also changed the variable you had named type to kind to avoid colliding with the built-in module of the same name.
class Device(object):
def connect(self, kind):
if kind == 'cli':
target = self._target = SSH()
elif kind == 'netconf':
target = self._target = Netconf()
else:
raise ValueError('Unknown device {!r}'.format(kind))
return target.connect(kind)
def __getattr__(self, name):
return getattr(self._target, name)
class SSH(object):
def connect(self, kind):
print('SSH.connect called with kind {!r}'.format(kind))
def execute(self, cmd):
print('SSH.execute called with cmd {!r}'.format(cmd))
class Netconf(object):
def connect(self, kind):
print('Netconf.connect called with kind {!r}'.format(kind))
def execute(self, cmd):
print('Netconf.execute called with cmd {!r}'.format(cmd))
d = Device()
d.connect('cli')
d.execute('cmd1')
d.connect('netconf')
d.execute('cmd2')
Output:
SSH.connect called with kind 'cli'
SSH.execute called with cmd 'cmd1'
Netconf.connect called with kind 'netconf'
Netconf.execute called with cmd 'cmd2'
You should implement the Strategy Pattern. The connect() method should instantiate the appropriate class (detach()ing from the previous if required) and store it, and then other methods should delegate to the stored object.
I'm trying to figure out if subclassing QtConcurrent and writing a run method inside it will work:
class Task(QtCore.QtConcurrent):
def run(self, function):
function()
Or is it completely useless?
It's completely useless, because QtConcurrent is a namespace, not a class.
Also, neither PyQt nor PySide provide any of the functionality provided by QtConcurrent, because it's all template-based and therefore impossible to wrap.
PS: the PySide documentation you linked to is for the ReduceOption enum. Since it's doubtful whether that enum has any use outside the QtConcurrent namespace, it's probably a bug that PySide includes it.
The class you are looking for is QRunnable.
I am stuck on the same problem in PyQt5. I guess the only solution is to do this locally:
def connect(self):
class ConnectThread(QThread):
def __init__(self, func):
super().__init__()
self.func = func
def run(self):
self.func()
self.connectThread = ConnectThread(self._connect)
self.connectThread.start()
def _connect(self):
if self._driver is None:
uri = self.uriString()
if uri and self.user and self.password:
self.statusMessage.emit("Connecting to the Graph Database....", -1, "color:blue;")
try:
self._driver = GraphDatabase.driver(uri, auth=(self.user, self.password))
self.statusMessage.emit("Connected!", 5000, "color:green;")
except Exception as e:
self.clearStatusMessage.emit()
Error(str(e)).exec_()
if __debug__:
raise e
And remember to set the thread to a member variable: self.thread = ... or else your thread reference will go out of scope, and most likely the thread object deleted.
You could also move your function-to-call into a local definition of it as Python allows both nested functions and classes within one another!
I'm having an issue where a class variable is set correctly and displayed correctly inside __init__() when using print, however, trying to display that same variable inside the __str__ method displays None. Three other variables generated the exact same way do not exhibit this behavior.
Here is my code:
class RestRequest(urllib2.Request):
def __init__(self, host, path, data=""):
self.host = host
self.data = data
self.path = path
print "RestRequest::init() path: %s" % self.path
print "RestRequest::init() data: %s" % self.data
print "RestRequest::init() host: %s" % self.host
urllib2.Request.__init__(self, self.path)
def __str__(self):
return "RestRequest::__str__() host='%s', path='%s', data='%s'" % (self.host, self.path, self.data)
The print statements inside __init__() display the correct values. The value of host inside __str__ is None. The path, method and data variables display correctly inside __str__.
Any ideas?
You're running into a naming clash with attributes on the super class. You'll need to change the names of your attributes -- or set them after urllib2.Request.__init__ (assuming your values are compatible with what the superclass wants).
urllib2.Request sets self.host = None in __init__. To prevent unexpected things happening, call the superclass __init__ earlier in the subclass __init__:
class RestRequest(urllib2.Request):
def __init__(self, host, path, data=""):
urllib2.Request.__init__(self, path) # sets self.host = None
self.host = host # resets to correct value
self.path = path
self.data = data
In a Javascript object when I would want to initiate several functions inside an object, say myObject, I would have an init function that would call those methods to me initialized and I would simple call myObject.init(). How would I do this in python? Would the following be ok?
class Test(object):
def __init__(self, arg):
self.arg = arg
def init(self):
self.some_function()
self.some_other_function()
def some_function(self):
pass
def some_other_function(self):
pass
my_test = Test("test")
my_test.init()
Thanks for reading!
Yes. That should work fine. but I would give some other name than init(), as it would be explicit and different from default __init__