Transforming Code into Beautiful, Idiomatic Python
6207 64 321857
Raymond Hettinger
Learn to take better advantage of Python's best features and improve existing code through a series of code transformations, "When you see this, do that instead."
Check out Raymond Hettinger's talks on YouTube. Here's one to get you started:
good list!
links for Raymond Hettinger ones
*
*
General python considerations :
First of all about time measurement you may use such a snippet:
from time import time, sleep class Timer(object): def __init__(self): self.last = time() def __call__(self): old = self.last self.last = time() return self.last - old @property def elapsed(self): return time() - self.last timer = Timer() sleep(2) print timer.elapsed print timer() sleep(1) print timer()
Then you could benchmark running code many times, and check for the diff.
About this, i comment inline :
with open(path, 'r') as file_obj: line = True while line: #iterate on realdines instead. try: line = file_obj.readline() match = reg_ex.match(line) index += match.group(1) #if match: # index.extend(match.group(1)) # or extend except AttributeError: pass
You previous code wat not really pythonic, you may want to try/except. Then try only on do in on the minimum possible lines.
The same notices apply to the second block of code.
If you need to read the same files multiple times. you could store them in RAM using StringIO or easier keep a {path: content} dict that you only read once.
Python regex are known to be slow, your data seems pretty simple, you may consider using split and strip methods on your inputlines.
striped=[l.split() for l in [c.strip() for c in file_desc.readlines()] if l]
I recommend you to read this : the correspondig video is here
This solution is pythonic, elegant and fast: (by the Famous Raymond Hettinger in one of his many conferences).
dict.setdefault is the dictionary method that initialises a key-value if the key is not found in dict as well as performing
dict.get for provided key.
l = ['foo','bar','help','this','guy'] d = {} for e in l: key = len(e) d.setdefault(key, []).append(name) print(d)
Output:
{3: ['foo', 'bar', 'guy'], 4: ['help', 'this']}
This solution is the modern way of the solution above:
defaultdict from
collection is a subclass of
dict that automatically initialises value to any given key that is not in the
defaultdict.
from collections import defaultdict l = ['foo','bar','help','this','guy'] d = defaultdict(list) for e in l: key = len(e) d[key].append(e) print(d)
Output:
defaultdict(<class 'list'>, {3: ['foo', 'bar', 'guy'], 4: ['help', 'this']})
I recently watched a talk by Raymond Hettinger which this post loosely reminded of, so I thought I'd link to it. I think it makes a great argument for the approach you described in you post:
Make the API work for you
First of all, I don't think overriding
__getattr__ is as sinful as that post might have you believe.
class MyAPI(object): base_args = {'token': 'foobarauthtoekn'} def __init__(self, ip): self._api = ServerProxy(ip) def _execute(self, method='', **kwargs): argdict = {'Method': method} argdict.update(MyAPI2.base_args) argdict.update(kwargs) self._api.Execute(argdict) def __getattr__(self, attr): return self.__dict__.get( attr, partial(self._execute, method=attr)) api = MyAPI('127.0.0.1') # Execute({'token': ..., 'Method': 'get_users', 'arg1': 'foo' ...}) = api.get_users(arg1='foo', arg2='bar') # Execute({'token': ..., 'Method': 'get_data', 'foo': 'stuff' ...}) = api.get_data(foo='stuff', bar='zxcv')
I like this because it's not a lot of code, and it lets us use
Execute in a more convenient way (with keyword args), without relying on support for that from the internal API.
Special behavior via metaclasses
The other approach prevents us having to override
__getattr__ in case I've underestimated how much of a mistake it is, and it could also be considered more pythonic, as we explicitly enumerate the methods we'll be providing with our API wrapper:
class APIMeta(type): def __new__(cls, clsname, bases, attrs): def exec_generic(name): base_args = {'token': 'foobarauthtoekn'} def exec_wrapper(self, params): args = {'Method': name} args.update(base_args) args.update(params) return self._api.Execute(args) return exec_wrapper new_attrs = { name: val if name.startswith('__') else exec_generic(name) for name, val in attrs.items() } return super(APIMeta, cls).__new__(cls, clsname, bases, new_attrs) class MyAPI(object, metaclass=APIMeta): def __init__(self, ip): self._api = ServerProxy(ip) def get_users(self): pass def get_data(self): pass # ...
In reality, I don't like this, since it's little more than a very convoluted way to write:
class MyAPI(object): _base_args = {'token': 'foobarauthtoken'} def __init__(self, ip): self._api = ServerProxy(ip) def get_users(self, params): argdict = {'Method': 'get_users'} argdict.update(MyAPI._base_args) argdict.update(params) return self._api.Execute(argdict) # ...
It will save you a considerable amount of typing if you have a lot of methods though, and it's also good practice in meta-programming if you're looking to get into that or deepen your understanding of the python language.
Raymond Hettinger suggested `nobreak` keyword to be introduced, however the proposal never got through... more [here]()
We do not use the same paradigms in Python. I'm pretty saddened to see all these "answers" using for/while loops.
This would be more pythonic (the Python Way):
average = sum(my_list) / len(my_list)
In Python we rarely (almost never) do the classic C for-loop (it is actually not implemented in the language). If you happen to do one, it's most likely that you're doing something wrong.
You can check this (and other R. Hettinger's) videos to get a grasp as to why. This core dev explains clearly.
Popular Videos 387
Submit Your Video
By clusmore 2017-09-20
Must watch:
I believe that the list comprehension will be faster than filter, but as always, any time you replace readable code with unreadable code for performance reasons, you damn well better time it.
Original Thread