1. Sequence join operator
The join operator (+) allows us to connect one sequence to another of the same type.
sequence1 + sequence2
For strings, this operation is not as good as putting all the substrings in a list or iterative object, and then calling a join method to connect all the contents together to save memory; for lists, the extended () method of list type is recommended to merge two or more list objects.
2. Sequence slices
>>> s = 'abcdefgh' >>> s[::-1] # Can be considered as a "flip" operation 'hgfedcba' >>> s[::2] # The operation of taking one from the other 'aceg
The beginning and ending primitive values of the slice index can exceed the length of the string. In other words, the starting index can be less than 0, and for the ending index, even if the index value of 100 elements does not exist, there will be no error.
>>> ('Faye', 'Leanna', 'Daylen')[-100:100] ('Faye', 'Leanna', 'Daylen')
There's a problem: there's a string, and we want to show it through a loop in the form of cutting off the last character each time. Here's a way to achieve this requirement:
>>> s = 'abcde' >>> i = -1 >>> for i in range(-1, -len(s), -1): ... print s[:i] ... abcd abc ab a
Because - 1 is already the "smallest" index. We can't use 0 as the index value because it slices up to the first element without showing anything:
>>> s[:0] ''
Our solution is to use another trick: using None as an index value
>>> s = 'abcde' >>> for i in [None] + range(-1, -len(s), -1): ... print s[:i] ... abcde abcd abc ab a
It seems that you can create a list containing only None, then add the output of range() to the list with the extend() function, or first create a list of range() output, then insert None at the top of the list, and then traverse the list:
>>> for i in [None].extend(range(-1, -len(s), -1)): ... print s[:i] ... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: iteration over non-sequence
The reason for this error is [None].extend(... ) The function returns None, which is neither a sequence type nor an iterative object.
3. Variable and Invariant Objects of Sequences
A string is an immutable data type. That is to say, its value can not be changed or modified. This means that if you want to modify a string, or intercept a substring, or connect another string at the end of the string, etc., you have to create a new string.
>> s = 'abc' >>> >>> id(s) 135060856 >>> >>> s += 'def' >>> id(s) 135057968
Changes to a character or a piece of character in a string are not allowed:
>>> s 'abcdef' >>> >>> s[2] = 'C' Traceback (innermost last): File "<stdin>", line 1, in ? AttributeError: __setitem__ >>> >>> s[3:6] = 'DEF' Traceback (innermost last): File "<stdin>", line 1, in ? AttributeError: __setslice__
The methods of variable objects that can change object values have no return values:
>>> music_media.sort()# No output? >>>
When using methods of variable objects such as sort(),extend() and reverse(), it should be noted that these operations will be performed in place in the list, that is to say, the contents of the existing list will be changed, but there is no return value! Yes, on the contrary, the string method does have a return value:
>>> 'leanna, silly girl!'.upper() 'LEANNA, SILLY GIRL!'
Although the tuple object itself is immutable, this does not mean that the mutable object contained in the tuple is immutable either:
>>> t = (['xyz', 123], 23, -103.4) >>> t (['xyz', 123], 23, -103.4) >>> t[0][1] 123 >>> t[0][1] = ['abc', 'def'] >>> t (['xyz', ['abc', 'def']], 23, -103.4)
4. Copies of Sequence Type Objects
Shallow copy of sequence type object is the default type copy, and can be implemented in the following ways: (1) complete slicing operation [:], (2) using factory functions, such as list(),dict(), etc., (3) using copy function of copy module.
>>> person = ['name', ['savings', 100.00]] >>> hubby = person[:] # slice copy >>> wifey = list(person) # fac func copy >>> [id(x) for x in person, hubby, wifey] [11826320, 12223552, 11850936]
When copying a list, the first object is immutable (a string type) and the second is variable (a list). That's why when making a shallow copy, the string is explicitly copied and a new string object is created, while the list element just copies its reference.
>>> hubby[0] = 'joe' >>> wifey[0] = 'jane' >>> hubby, wifey (['joe', ['savings', 100.0]], ['jane', ['savings', 100.0]]) >>> hubby[1][1] = 50.00 >>> hubby, wifey (['joe', ['savings', 50.0]], ['jane', ['savings', 50.0]])
To get a full copy or a deep copy --- create a new container object that contains references to the original object element (reference) in a completely new copy --- you need the copy.deepcopy() function.
>>> person = ['name', ['savings', 100.00]] >>> hubby = person >>> import copy >>> wifey = copy.deepcopy(person) >>> [id(x) for x in person, hubby, wifey] [12242056, 12242056, 12224232] >>> hubby[0] = 'joe' >>> wifey[0] = 'jane' >>> hubby, wifey (['joe', ['savings', 100.0]], ['jane', ['savings', 100.0]]) >>> hubby[1][1] = 50.00 >>> hubby, wifey (['joe', ['savings', 50.0]], ['jane', ['savings', 100.0]])
Non-container types (such as numbers, strings and other "atomic" objects, such as code, types, xrange objects, etc.) are not copied.
If the tuple variable contains only atom-type objects, a deep copy of it will not occur.
>>> person = ['name', ('savings', 100.00)] >>> newPerson = copy.deepcopy(person) >>> [id(x) for x in person, newPerson] [12225352, 12226112] >>> [id(x) for x in person] [9919616, 11800088] >>> [id(x) for x in newPerson] [9919616, 11800088]
5. Access the values in the dictionary
If we want to access a data element in the dictionary and it has no corresponding key in the dictionary, an error will occur:
>>> dict2['server'] Traceback (innermost last): File "<stdin>", line 1, in ? KeyError: server
Check whether there is a key in a dictionary using in or not in operators:
>>> 'server' in dict False >>> 'name' in dict True
6. Dictionary Sorting
mydict = {'carl':40, 'alan':2, 'bob':1, 'danny':3}
key-based sorting:
for key in sorted(mydict.iterkeys()):
print "%s: %s" % (key, mydict[key])
Results:
alan: 2 bob: 1 carl: 40 danny: 3
value-based sorting:
for key, value in sorted(mydict.iteritems(), key=lambda (k,v): (v,k)):
print "%s: %s" % (key, value)
Results:
bob: 1 alan: 2 danny: 3 carl: 40
Take out the maximum and minimum key:
min_key = min(mydict.keys()) max_key = max(mydict.keys())
Using iterator traversal, dict has several iterators: iteritems, iterkeys, itervalues. Here's an example of iteritems:
for k,v in myDict.iteritems():
print k,v
7. Determine whether a list is empty
Traditional ways:
if len(mylist):
# Do something with my list
else:
# The list is empty
Since an empty list itself is equivalent to False, it can be directly:
if mylist:
# Do something with my list
else:
# The list is empty
8. Obtaining indexes while traversing list s
Traditional ways:
i = 0
for element in mylist:
# Do something with i and element
i += 1
This is more concise:
for i, element in enumerate(mylist):
# Do something with i and element
pass
9.list sort
Sorting by an attribute in a list containing an element is a very common operation. For example, let's first create a list of people:
class Person(object):
def __init__(self, age):
self.age = age
persons = [Person(age) for age in (14, 78, 42)]
The traditional way is:
def get_sort_key(element):
return element.age
for element in sorted(persons, key=get_sort_key):
print "Age:", element.age
A more concise and readable way is to use the operator module in the Python standard library. The attrgetter method first returns the read attribute value as a parameter to the sorted method. The operator module also includes itemgetter and method caller methods, which work literally.
from operator import attrgetter
for element in sorted(persons, key=attrgetter('age')):
print "Age:", element.age
10. Grouping elements in Dictionary
class Person(object):
def __init__(self, age):
self.age = ageperson
s = [Person(age) for age in (78, 14, 78, 42, 14)]
If we want to group by age now, one way is to use the in operator:
persons_by_age = {}
for person in persons:
age = person.age
if age in persons_by_age:
persons_by_age[age].append(person)
else:
persons_by_age[age] = [person]
assert len(persons_by_age[78]) == 2
By contrast, the way to use defaultdict method in collections module is more readable. Defaultdict will create a corresponding value for each key that does not exist using the accepted parameters. Here we pass a list, so it will create a list-type value for each key:
from collections import defaultdict
persons_by_age = defaultdict(list)
for person in persons:
persons_by_age[person.age].append(person)