This program goes through 7 common logical functions (AND
, OR
, NOT
, NOR
, XOR
, XNOR
, and NAND
) and generates and prints truth tables for them all.
#!/usr/bin/env python2
# coding:utf-8
import operator
import itertools
table = list(itertools.product([False, True], repeat=2))
ops={'AND': ('∧', (lambda a,b:bool(operator.and_(a,b)))),
'OR': ('∨', (lambda a,b:bool(operator.or_(a,b)))),
'NOT': ('¬', (lambda a,b:bool(operator.not_(a)))),
'NOR': ('↓', (lambda a,b:bool(operator.not_(operator.or_(a,b))))),
'XOR': ('↮', (lambda a,b:bool(operator.xor(a,b)))),
'XNOR': ('↔', (lambda a,b:bool(operator.not_(operator.xor(a,b))))),
'NAND': ('↑', (lambda a,b:bool(operator.not_(operator.and_(a,b)))))}
pad = lambda x:(str(x) if len(str(x)) == 5 else str(x) + ' ')
for i in ops.keys():
print i +',',ops[i][0],'\n' + '-'*25
for j in table:
print '|', pad(j[0]), '|', pad(j[1]), '|', pad(ops[i][1](j[0],j[1])), '|'
print '-'*25, '\n'
I don't care much about the speed, but how can I improve the style and follow the PEP guidelines in this program?
1 Answer 1
You should make a class. This lets you consolidate the implementation to be consistent, and simplifies a number of the details. You can also implement __str__
and __repr__
to make it easier to print them. Use string formatting for this
class LogicalOperator(object):
def __init__(self, name, symbol, functor):
self.name = name
self.symbol = symbol
self.functor = functor
def __call__(self, a, b):
return bool(functor(a, b))
def __str__(self):
return self.name
def __repr__(self):
return "{}, {}".format(self.name, self.symbol)
Inheriting from namedtuple
makes this easier (thanks to Caridorc for pointing out in the comments).
from collections import namedtuple
class LogicalOperator(namedtuple('LogicalOperator', 'name symbol functor')):
# no __init__ now
# rest is unchanged
This way you've separated your concerns. The class encapsulates "what is a logical operator and how do I make it print pretty", and then we use it as necessary to get value and formatting for it.
Then we can still create all of our logical operators, but we do it with classes and a tuple instead of a dict and tuples.
ops = (
LogicalOperator('AND', '∧', operator.and_),
LogicalOperator('OR', '∨', operator.or_),
LogicalOperator('NOT', '¬', lambda a, _: not a),
LogicalOperator('NOR', '↓', lambda a, b: not (a or b)),
LogicalOperator('XOR', '↮', operator.xor),
LogicalOperator('XNOR', '↔', lambda a, b: not (a ^ b)),
LogicalOperator('NAND', '↑', lambda a, b: not (a and b))
)
A better way to pad strings is to use string.rjust
. An even better way is to use the Format Specification Mini-Language.
Then we can put it all together.
if __name__ == '__main__':
column_width = 25
table = list(itertools.product([False, True], repeat=2))
for op in ops:
print(op)
print("-"*column_width)
for left, right in table:
print("|{:^5}|{:^5}|{:^5}|".format(left, right, op(left, right)))
print("-"*column_width)
Also, you could use more whitespace throughout. Makes it easier to read.
-
\$\begingroup\$ Thanks for answering. Also, I don't know if you noticed but I'm using python 2. I didn't see any places where it made a difference, but the print statements still had parentheses. \$\endgroup\$user95591– user955912016年07月06日 20:41:20 +00:00Commented Jul 6, 2016 at 20:41
-
\$\begingroup\$ having the parenthesis doesn't hurt anything in Python 2, and it'll make it much easier if you ever decide to port it to Python 3 \$\endgroup\$Dan Oberlam– Dan Oberlam2016年07月06日 21:34:32 +00:00Commented Jul 6, 2016 at 21:34
-
1\$\begingroup\$ Inheriting from named tuple allows you to avoid the verbose
__init__
\$\endgroup\$Caridorc– Caridorc2016年07月07日 13:44:24 +00:00Commented Jul 7, 2016 at 13:44 -
\$\begingroup\$ Also, you could save some memory by adding
__slots__ = ()
to your namedtuple definition. \$\endgroup\$Perry– Perry2016年07月07日 21:00:48 +00:00Commented Jul 7, 2016 at 21:00 -
\$\begingroup\$ @ppperry you could, but there isn't really a reason to. Saving memory (esp in Python) is generally not worthwhile; only do it when you need to. Furthermore, it can be less accessible to people who aren't familiar with it, and prevents introspection with
vars()
\$\endgroup\$Dan Oberlam– Dan Oberlam2016年07月07日 21:50:26 +00:00Commented Jul 7, 2016 at 21:50