📜 ⬆️ ⬇️

Things to remember when programming in Python

Zen Python



Studying the culture that surrounds the language brings you one step closer to the best programmers. If you still haven't read Zen of Python, then open the Python interpreter and enter import this . For each item in the list you will find an example here.

Once my attention caught:
')
Beautiful is better than ugly

UPDATE: There have been many discussions on this article on Hacker News . A few corrections from them.

Give me a function that takes a list of numbers and returns only even numbers divided by two.

#----------------------------------------------------------------------- halve_evens_only = lambda nums: map(lambda i: i/2, filter(lambda i: not i%2, nums)) #----------------------------------------------------------------------- def halve_evens_only(nums): return [i/2 for i in nums if not i % 2] 


Remember very simple things in python



Exchange of values ​​of two variables:

  a, b = b, a 


Stepping argument for slices. For example:

  a = [1,2,3,4,5] >>> a[::2] # iterate over the whole list in 2-increments [1,3,5] 


A special case of x [:: - 1] is a means of expressing x.reverse () .

  >>> a[::-1] [5,4,3,2,1] 


UPDATE: Keep in mind x.reverse () reverses the list, and slices give you the ability to do this:

  >>> x[::-1] [5, 4, 3, 2, 1] >>> x[::-2] [5, 3, 1] 




  def function(x, l=[]): # Don't do this def function(x, l=None): # Way better if l is None: l = [] 


UPDATE: I understand that I did not explain why. I recommend reading the Fredrik Lundh article. In short, this design is sometimes found. “Default values ​​are always calculated if and only when def is declared for execution.”



iteritems use generators and hence it is better when working with very large lists.

  d = {1: "1", 2: "2", 3: "3"} for key, val in d.items() # builds complete list when called. for key, val in d.iteritems() # calls values only when requested. 


This is similar to range and xrange when xrange calls values ​​only when asked.

UPDATE: Note that iteritems , iterkeys , itervalues ​​are removed from Python 3.x. dict.keys () , dict.items () and dict.values ​​() will return views instead of a list. docs.python.org/release/3.1.5/whatsnew/3.0.html#views-and-iterators-instead-of-l-



Do not do it:

  if type(s) == type(""): ... if type(seq) == list or \ type(seq) == tuple: ... 


it is better:

  if isinstance(s, basestring): ... if isinstance(seq, (list, tuple)): ... 


Why you should not do this: stackoverflow.com/a/1549854/504262

Notice that I use basestring and not str , as you can try to check unicode conformance to str . For example:

  >>> a=u'aaaa' >>> print isinstance(a, basestring) True >>> print isinstance(a, str) False 


This happens because in Python versions <3.0 there are two string types: str and unicode :

  object | | basestring / \ / \ str unicode 




Python has various types of data containers that are the best alternative to the basic list and dict in various cases.

In most cases, these are used:

UPDATE: I know most have not used it. Inattention on my part. Some may write this:

  freqs = {} for c in "abracadabra": try: freqs[c] += 1 except: freqs[c] = 1 


Some might say it would be better:

  freqs = {} for c in "abracadabra": freqs[c] = freqs.get(c, 0) + 1 


Rather, use a collection of type defaultdict :

  from collections import defaultdict freqs = defaultdict(int) for c in "abracadabra": freqs[c] += 1 


Other collections

  namedtuple() # factory function for creating tuple subclasses with named fields deque # list-like container with fast appends and pops on either end Counter # dict subclass for counting hashable objects OrderedDict # dict subclass that remembers the order entries were added defaultdict # dict subclass that calls a factory function to supply missing values 


UPDATE: As noted in several comments on Hacker News, I could use Counter instead of defaultdict .

  >>> from collections import Counter >>> c = Counter("abracadabra") >>> c['a'] 5 




  __eq__(self, other) # Defines behavior for the equality operator, ==. __ne__(self, other) # Defines behavior for the inequality operator, !=. __lt__(self, other) # Defines behavior for the less-than operator, <. __gt__(self, other) # Defines behavior for the greater-than operator, >. __le__(self, other) # Defines behavior for the less-than-or-equal-to operator, <=. __ge__(self, other) # Defines behavior for the greater-than-or-equal-to operator, >=. 


There are a number of other magical methods.



  x = 3 if (y == 1) else 2 


This code does exactly what it sounds like: “assign 3 to x if y = 1 , otherwise assign 2 to x ”. You can also apply this if you have something more complicated:

  x = 3 if (y == 1) else 2 if (y == -1) else 1 


Although at some point it goes too far.

Note that you can use an if ... else expression in any expression. For example:

  (func1 if y == 1 else func2)(arg1, arg2) 


Here func1 will be called if y = 1 , and func2 otherwise. In both cases, the corresponding function will be called with the arguments arg1 and arg2 .

Similarly, the following also holds true:

  x = (class1 if y == 1 else class2)(arg1, arg2) 


where class1 and class2 are classes.



UPDATE: One of the commentators with Hacker News mentioned: “Using ellipsis to get all the elements is in violation of the principle of“ Only One Way Achievement of the Goal “. The standard notation is [:] . ” I agree with him. The best example of using NumPy on stackoverflow is :

Dots are used to slice multidimensional data structures.

In this situation, this means that you need to expand the multidimensional slice in all dimensions.

Example:

  >>> from numpy import arange >>> a = arange(16).reshape(2,2,2,2) 


You now have a 4-D matrix of about 2x2x2x2. In order to select all the first elements of the 4th dimension, you can use the ellipsis:

  >>> a[..., 0].flatten() array([ 0, 2, 4, 6, 8, 10, 12, 14]) 


which is equivalent to writing:

  >>> a[:,:,:,0].flatten() array([ 0, 2, 4, 6, 8, 10, 12, 14]) 


Previous offers.

When creating a class, you can use __getitem__ to ensure that your class object behaves like a dictionary. Take this class as an example:

  class MyClass(object): def __init__(self, a, b, c, d): self.a, self.b, self.c, self.d = a, b, c, d def __getitem__(self, item): return getattr(self, item) x = MyClass(10, 12, 22, 14) 


Because __getitem__, you can get the value a of the object x as x ['a'] . This is probably a known fact.

This object is used to extend Python slices docs.python.org/library/stdtypes.html#bltin-ellipsis-object So if we add:

  def __getitem__(self, item): if item is Ellipsis: return [self.a, self.b, self.c, self.d] else: return getattr(self, item) 


We can use x [...] to get a list of all the elements.

  >>> x = MyClass(11, 34, 23, 12) >>> x[...] [11, 34, 23, 12] 





PS



This is a translation of the Satyajit Ranjeev post - " A few things to remember while coding in python. ". But there was not enough 0.5 karma in the translation hub, and it does not allow saving the draft, so I post it as it is. Please send all comments on the translation and spelling in PM, and do not kick much =)

Source: https://habr.com/ru/post/144614/


All Articles