I'm writing a driver in Python 2.6 and I need it to be reverse compatible with a previous implementation (I don't have access to the source code).
class new_driver ():
def output(self, state):
if state == True:
self.set_ouput_on()
else:
self.set_output_off()
...
The odd thing is that to keep compatibility I have to pass this output using the format
nd = new_driver()
nd.output = True
How do I pass a value in this way?
Edit: To clarify: my "output" function has to receive the value True in this way in order to execute the function self.set_output_on()
Try using the #property decorator:
#property
def output(self):
return self... #not sure how you are tracking output on/off
#output.setter
def output(self, state):
if state:
self.set_output_on()
else:
self.set_output_off()
Related
class CommandManager:
def __init__(self):
self.commands = []
def add_command(self, command: Command):
if command is None:
return None
for target in self.commands:
if target.name is command.name:
return None
print(command.name, command.description, command.usage, command.min_arguments) # debug
self.commands.append(command)
return command
def get_command(self, name):
if name is None:
return None
for target in self.commands:
if name is target.name:
return target
return None
What's wrong with this code? Adding to the array and looking for it in the add_command method works fine, but inget_command it does not find it. No value is None.
is tests for identity, not equality. That means Python simply compares the memory address a object resides in.
you should use == operator to test equality of a string like:
if name == target.name:
is operator tests if two variables point to the same object. Use == instead.
if name == target.name:
(I am new to Python and OOP so please let me know if I use nonsensical language at any point.)
The book Problems in Data Structures and Algorithms implements code for binary and unary logic gates in a hierarchical fashion. Please see the bottom of my question for the full relevant code.
My particular query is: in the Connector class, in the constructor, there is the line
tgate.setNextPin(self)
Referring back to the unary gate where the setNextPin function is defined:
def setNextPin(self,source):
if self.pin == None:
self.pin = source
else:
print("Cannot Connect: NO EMPTY PINS on this gate")
The "source" in the function setNextPin is the input of the function setNextPin. So when I see the line tgate.setNextPin(self), it tells me to go back to the unary class (tgate) to find the function setNextPin, and that the input ("source") of the setNextPin function is self, which in this case is an instance of the Connector class. However, I don't really see how this makes sense. I don't see how a connector class could be the input for the variable "source" in setNextPin.
The full code:
class LogicGate:
def __init__(self,n):
self.name = n
self.output = None
def getName(self):
return self.name
def getOutput(self):
self.output = self.performGateLogic()
return self.output
class UnaryGate(LogicGate):
def __init__(self,n):
LogicGate.__init__(self,n)
self.pin = None
def getPin(self):
if self.pin == None:
return int(input("Enter Pin input for gate "+self.getName()+"-->"))
else:
return self.pin.getFrom().getOutput()
def setNextPin(self,source):
if self.pin == None:
self.pin = source
else:
print("Cannot Connect: NO EMPTY PINS on this gate")
class NotGate(UnaryGate):
def __init__(self,n):
UnaryGate.__init__(self,n)
def performGateLogic(self):
if self.getPin():
return 0
else:
return 1
class Connector:
def __init__(self, fgate, tgate):
self.fromgate = fgate
self.togate = tgate
tgate.setNextPin(self)
def getFrom(self):
return self.fromgate
def getTo(self):
return self.togate
The Connector class represents the wires that are used to connect logic gates to each other. setNextPin() is given a Connector, and associates this with the pin property. When it wants to get the logic gate that provides its input, it calls self.pin.getFrom(), which goes to the Connector getFrom() method, which then returns the Connector's fromgate property, which will be the gate at the other end of the wire.
First we should note that setNextPin(self,source) is a method of binaryGate class as well unaryGate.
In the function definition setNextPin(self,source), self is tgate(alias of a Gate class) and source is the instance of Connector class. Suppose aaa-->bbb (a is connected to b) then the connector will be a alias of object bbb's PIN and connector attribute .fromGate will a alias to previous link that is aaa.
I'm wondering how could one create a program to detect the following cases in the code, when comparing a variable to hardcoded values, instead of using enumeration, dynamically?
class AccountType:
BBAN = '000'
IBAN = '001'
UBAN = '002'
LBAN = '003'
I would like the code to report (drop a warning into the log) in the following case:
payee_account_type = self.get_payee_account_type(rc) # '001' for ex.
if payee_account_type in ('001', '002'): # Report on unsafe lookup
print 'okay, but not sure about the codes, man'
To encourage people to use the following approach:
payee_account_type = self.get_payee_account_type(rc)
if payee_account_type in (AccountType.IBAN, AccountType.UBAN):
print 'do this for sure'
Which is much safer.
It's not a problem to verify the == and != checks like below:
if payee_account_type == '001':
print 'codes again'
By wrapping payee_account_type into a class, with the following __eq__ implemented:
class Variant:
def __init__(self, value):
self._value = value
def get_value(self):
return self._value
class AccountType:
BBAN = Variant('000')
IBAN = Variant('001')
UBAN = Variant('002')
LBAN = Variant('003')
class AccountTypeWrapper(object):
def __init__(self, account_type):
self._account_type = account_type
def __eq__(self, other):
if isinstance(other, Variant):
# Safe usage
return self._account_type == other.get_value()
# The value is hardcoded
log.warning('Unsafe comparison. Use proper enumeration object')
return self._account_type == other
But what to do with tuple lookups?
I know, I could create a convention method wrapping the lookup, where the check can be done:
if IbanUtils.account_type_in(account_type, AccountType.IBAN, AccountType.UBAN):
pass
class IbanUtils(object):
def account_type_in(self, account_type, *types_to_check):
for type in types_to_check:
if not isinstance(type, Variant):
log.warning('Unsafe usage')
return account_type in types_to_check
But it's not an option for me, because I have a lot of legacy code I cannot touch, but still need to report on.
Two questions regarding the with statement in Python. They come from a real-life problem so I keep it real. I am dealing with a pinch valve in order to control the flow in a pipe.
The program drives the valve with a class looking like that:
class Valve(object):
"""This class drives a pinch valve."""
def __init__(self):
self.close()
def open(self):
print('Open the valve.')
self.state = 'opened'
def close(self):
print('Close the valve.')
self.state = 'closed'
def print_state(self):
print('The valve is '+self.state+'.')
For some operations, I need exactly what the with statement does with a file (the file is closed at the end or if an error is raised), so I added a function to the class Valve and another class:
def opened(self):
return ContextManagerOpenedValve(self)
class ContextManagerOpenedValve(object):
def __init__(self, valve):
self.valve = valve
def __enter__(self):
self.valve.open()
return self.valve
def __exit__(self, type, value, traceback):
self.valve.close()
Then these lines seem to work as I expected:
def do_something():
print('For the sake of simplicity, this function does nothing.')
valve = Valve()
valve.print_state()
with valve.opened():
valve.print_state()
do_something()
valve.print_state()
My first question: what is the right way to obtain such result? Am I right to use the with statement for that? Can't I do that in a smarter way without defining the class ContextManagerOpenedValve?
Then I need to do something like this:
USE_VALVE = False # or USE_VALVE = True
if USE_VALVE:
with valve.opened():
do_something()
else:
do_something()
I dislike this solution since the function do_something is run anyway so it would be much nicer to avoid the repetition of "do_something()".
My second question: Is there a way to obtain the same result without
repeating do_something() twice ?
Sure, you can do it like so:
def valve_control(valve, use_value=False):
if use_value:
return ContextManagerOpenedValve(valve)
else:
return SomeFakeContextManager()
Then your call looks like:
with valve_control(value, USE_VALVE):
do_something()
I have a nested function that I'm using as a callback in pyglet:
def get_stop_function(stop_key):
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
return stop_on_key
pyglet.window.set_handler('on_key_press', get_stop_function('ENTER'))
But then I run into problems later when I need to reference the nested function again:
pyglet.window.remove_handler('on_key_press', get_stop_function('ENTER'))
This doesn't work because of the way python treats functions:
my_stop_function = get_stop_function('ENTER')
my_stop_function is get_stop_function('ENTER') # False
my_stop_function == get_stop_function('ENTER') # False
Thanks to two similar questions I understand what is going on but I'm not sure what the workaround is for my case. I'm looking through the pyglet source code and it looks like pyglet uses equality to find the handler to remove.
So my final question is: how can I override the inner function's __eq__ method (or some other dunder) so that identical nested functions will be equal?
(Another workaround would be to store a reference to the function myself, but that is duplicating pyglet's job, will get messy with many callbacks, and anyways I'm curious about this question!)
Edit: actually, in the questions I linked above, it's explained that methods have value equality but not reference equality. With nested functions, you don't even get value equality, which is all I need.
Edit2: I will probably accept Bi Rico's answer, but does anyone know why the following doesn't work:
def get_stop_function(stop_key):
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
stop_on_key.__name__ = '__stop_on_' + stop_key + '__'
stop_on_key.__eq__ = lambda x: x.__name__ == '__stop_on_' + stop_key + '__'
return stop_on_key
get_stop_function('ENTER') == get_stop_function('ENTER') # False
get_stop_function('ENTER').__eq__(get_stop_function('ENTER')) # True
You could create a class for your stop functions and define your own comparison method.
class StopFunction(object):
def __init__(self, stop_key):
self.stop_key = stop_key
def __call__(self, symbol, _):
if symbol == getattr(pyglet.window.key, self.stop_key):
pyglet.app.exit()
def __eq__(self, other):
try:
return self.stop_key == other.stop_key
except AttributeError:
return False
StopFunciton('ENTER') == StopFunciton('ENTER')
# True
StopFunciton('ENTER') == StopFunciton('FOO')
# False
the solution is to keep a dictionary containing the generated functions around,
so that when you make the second call, you get the same object as in the first call.
That is, simply build some memoization logic, or use one of the libraries
existing with memoizing decorators:
ALL_FUNCTIONS = {}
def get_stop_function(stop_key):
if not stop_key in ALL_FUNCTIONS:
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
ALL_FUNCTIONS[stop_key] = stop_on_key
else:
stop_on_key = ALL_FUNCTIONS[stop_key]
return stop_on_key
You can generalize Bi Rico's solution to allow wrapping any functions up with some particular equality function pretty easily.
The first problem is defining what the equality function should check. I'm guessing for this case, you want the code to be identical (meaning functions created from the same def statement will be equal, but two functions created from character-for-character copies of the def statement will not), and the closures to be equal (meaning that if you call get_stop_function with two equal but non-identical stop_keys the functions will be equal), and nothing else to be relevant. But that's just a guess, and there are many other possibilities.
Then you just wrap a function the same way you'd wrap any other kind of object; just make sure __call__ is one of the things you delegate:
class EqualFunction(object):
def __init__(self, f):
self.f = f
def __eq__(self, other):
return (self.__code__ == other.__code__ and
all(x.cell_contents == y.cell_contents
for x, y in zip(self.__closure__, other.__closure__)))
def __getattr__(self, attr):
return getattr(self.f, attr)
def __call__(self, *args, **kwargs):
return self.f(*args, **kwargs)
If you want to support other dunder methods that aren't required to go through getattr (I don't think any of them are critical for functions, but I could be wrong…), either do it explicitly (as with __call__) or loop over them and add a generic wrapper to the type for each one.
To use the wrapper:
def make_f(i):
def f():
return i
return EqualFunction(f)
f1 = f(0)
f2 = f(0.0)
assert f1 == f2
Or, notice that EqualFunction actually works as a decorator, which may be more readable.
So, for your code:
def get_stop_function(stop_key):
#EqualFunction
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
return stop_on_key