from __future__ import print_function
import os
import psutil
process = psutil.Process(os.getpid())
print('init:', process.memory_info().rss / 1024 / 1024, 'MB') # 11 MB
x = range(2**25)
print('x', process.memory_info().rss / 1024 / 1024, 'MB') # 1054 MB
y = x[1:] # deep copy
print('x, y', process.memory_info().rss / 1024 / 1024, 'MB') # 1310 MB
z = x[1:] # deep copy
print('x, y, z', process.memory_info().rss / 1024 / 1024, 'MB') # 1566 MB
## Define function in the runtime
# import sys
#
# for line in sys.stdin:
# line = line.rstrip()
# if int(line) > 0:
# def foo():
# print line, 'positive'
# else:
# def foo():
# print line, 'negative'
#
# foo()
## Pit falls of closure
# from __future__ import print_function
# def buggy_maker(my_list):
# acts = []
# for i in my_list:
# acts.append(lambda: print(i))
# return acts
# for act in buggy_maker([1,2,3]):
# act() # always print 3, instead of 1, 2, 3
#
# def buggy_maker2():
# acts = []
# i = 1
# acts.append(lambda: print(i))
# i = 2
# acts.append(lambda: print(i))
# return acts
# for act in buggy_maker2():
# act() # always print 2, instead of 1, 2
## Usage of global
# def foo():
# global s
# s = None
# print s
#
# foo()
# print s
Identifier Type | Format | Example |
---|---|---|
Class | Camel case | class StringManipulator(): |
Function | Words joined by _ | def multi_word_name(words): |
Constant | All uppercase | SECRET_KEY = 42 |
Basically everything not listed should follow the variable/function naming conventions of ‘Words joined by an underscore’.
# Avoid repeating variable name in compound if statement
is_generic_name = name in ('Tom', 'Dick', 'Harry')
# Use else to execute code after a for loop concludes
for user in get_all_users():
print ('Checking {}'.format(user))
for email_address in user.get_all_email_addresses():
if email_is_malformed(email_address):
print ('Has a malformed email address!')
break
else:
# The else clause is executed after the iterator is
# exhausted, unless the loop was ended prematurely
# due to a break statement
print ('All email addresses are valid!')
import random
def get_data():
"""Return 3 random integers between 0 and 9"""
return random.sample(range(10), 3)
def consume():
"""Displays a running average across lists of integers sent to it"""
running_sum = 0
data_items_seen = 0
while True:
data = yield
data_items_seen += len(data)
running_sum += sum(data)
print('The running average is {}'.format(running_sum / float(data_items_seen)))
def produce(consumer):
"""Produces a set of values and forwards them to the pre-defined consumer
function"""
while True:
data = get_data()
print('Produced {}'.format(data))
consumer.send(data)
yield
if __name__ == '__main__':
consumer = consume()
consumer.send(None)
producer = produce(consumer)
for _ in range(10):
print('Producing...')
next(producer)
from __future__ import print_function
class Foo(object):
def __init__(self):
self.name = 'name'
self._name = '_name'
self.__name = '__name'
class Bar(Foo):
def __init__(self):
super(Bar, self).__init__()
foo = Foo()
bar = Bar()
print(foo.name) # name
print(foo._name) # _name
print(foo.__name) # ValueError
print(foo._Foo__name) # field __name has been changed to _Foo__name
print(bar.name) # name
print(bar._name) # _name
print(bar.__name) # ValueError
print(foo._Foo__name) # field __name has been changed to _Foo__name
# List
# Avoid using '', [], and {} as default parameters to functions
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
# This will print
# [1]
# [1, 2]
# [1, 2, 3]
# Dict:
log_severity = None
if 'severity' in configuration:
log_severity = configuration['severity']
else:
log_severity = 'Info'
# is equivalent to
log_severity = configuration.get('severity', 'Info')
# Set: the mathematical set operations
A & B # Intersection
A | B # Union
A - B # The set of elements in A but not B, not necessarily equal to B -A
A ^ B # Symmetric Difference
from __future__ import print_function
from timeit import default_timer as timer
def timeit(F):
def FF(*args, **kwargs):
start = timer()
F(*args, **kwargs)
end = timer()
print(F.__name__ + ':', end - start)
return FF
# This is equivalent to F = timeit(F)
@timeit
def computation_func(x):
count = 0
for i in xrange(x):
count += i
class Foo(object):
@timeit
def computation_func(self, x):
count = 0
for i in xrange(x):
count += i
computation_func(2**8) # 2.78949737549e-05
Foo().computation_func(2**8) # 2.40802764893e-05
from __future__ import print_function
registry = {}
def register(obj):
registry[obj.__name__] = obj
return obj
@register
def spam(x):
return (x ** 2)
@register
def ham(x):
return (x ** 3)
print('Registry:')
for name in registry:
print(name, '=>', registry[name], type(registry[name]))
# Registry:
# ham => <function ham at 0x7fd0de4b48c0> <type 'function'>
# spam => <function spam at 0x7fd0de4b4848> <type 'function'>
print('\nRegistry calls:')
for name in registry:
print(name, '=>', registry[name](2)) # Invoke from registry
# Registry calls:
# ham => 8
# spam => 4
## Naming
| Identifier Type | Format | Example |
|-----------------|-------------------|-------------------------------|
| Class | Camel case | `class StringManipulator():` |
| Function | Words joined by _ | `def multi_word_name(words):` |
| Constant | All uppercase | `SECRET_KEY = 42` |
Basically everything not listed should follow the variable/function naming conventions
of ‘Words joined by an underscore’.
## Control flow
```python
# Avoid repeating variable name in compound if statement
is_generic_name = name in ('Tom', 'Dick', 'Harry')
# Use else to execute code after a for loop concludes
for user in get_all_users():
print ('Checking {}'.format(user))
for email_address in user.get_all_email_addresses():
if email_is_malformed(email_address):
print ('Has a malformed email address!')
break
else:
# The else clause is executed after the iterator is
# exhausted, unless the loop was ended prematurely
# due to a break statement
print ('All email addresses are valid!')
G = (x ** 2 for x in range(4)) # Generator expression: make an iterable
import random
def get_data():
"""Return 3 random integers between 0 and 9"""
return random.sample(range(10), 3)
def consume():
"""Displays a running average across lists of integers sent to it"""
running_sum = 0
data_items_seen = 0
while True:
data = yield
data_items_seen += len(data)
running_sum += sum(data)
print('The running average is {}'.format(running_sum / float(data_items_seen)))
def produce(consumer):
"""Produces a set of values and forwards them to the pre-defined consumer
function"""
while True:
data = get_data()
print('Produced {}'.format(data))
consumer.send(data)
yield
if __name__ == '__main__':
consumer = consume()
consumer.send(None)
producer = produce(consumer)
for _ in range(10):
print('Producing...')
next(producer)
from __future__ import print_function
class Foo(object):
def __init__(self):
self.name = 'name'
self._name = '_name'
self.__name = '__name'
class Bar(Foo):
def __init__(self):
super(Bar, self).__init__()
foo = Foo()
bar = Bar()
print(foo.name) # name
print(foo._name) # _name
print(foo.__name) # ValueError
print(foo._Foo__name) # field __name has been changed to _Foo__name
print(bar.name) # name
print(bar._name) # _name
print(bar.__name) # ValueError
print(foo._Foo__name) # field __name has been changed to _Foo__name
# List
# Avoid using '', [], and {} as default parameters to functions
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
# This will print
# [1]
# [1, 2]
# [1, 2, 3]
# Dict:
log_severity = None
if 'severity' in configuration:
log_severity = configuration['severity']
else:
log_severity = 'Info'
# is equivalent to
log_severity = configuration.get('severity', 'Info')
# Set: the mathematical set operations
A & B # Intersection
A | B # Union
A - B # The set of elements in A but not B, not necessarily equal to B -A
A ^ B # Symmetric Difference
from __future__ import print_function
from timeit import default_timer as timer
def timeit(F):
def FF(*args, **kwargs):
start = timer()
F(*args, **kwargs)
end = timer()
print(F.__name__ + ':', end - start)
return FF
# This is equivalent to F = timeit(F)
@timeit
def computation_func(x):
count = 0
for i in xrange(x):
count += i
class Foo(object):
@timeit
def computation_func(self, x):
count = 0
for i in xrange(x):
count += i
computation_func(2**8) # 2.78949737549e-05
Foo().computation_func(2**8) # 2.40802764893e-05
from __future__ import print_function
registry = {}
def register(obj):
registry[obj.__name__] = obj
return obj
@register
def spam(x):
return (x ** 2)
@register
def ham(x):
return (x ** 3)
print('Registry:')
for name in registry:
print(name, '=>', registry[name], type(registry[name]))
# Registry:
# ham => <function ham at 0x7fd0de4b48c0> <type 'function'>
# spam => <function spam at 0x7fd0de4b4848> <type 'function'>
print('\nRegistry calls:')
for name in registry:
print(name, '=>', registry[name](2)) # Invoke from registry
# Registry calls:
# ham => 8
# spam => 4
The five major components of the module import search path are
- the top-level script’s home directory (the directory containing it)
- all directories listed in the
PYTHONPATH
environment variable - the standard library directories
- all directories listed in
.pth
path files located in standard places - the site-packages root directory for third-party extension installs.
A module will only be imported once in every execution.
# Diamond Dependency
# +---+
# | |
# +----+ A +----+
# | | | |
# | +---+ |
# +-v-+ +-v-+
# | | | |
# | B | | C |
# | | | |
# +-+-+ +-+-+
# | +---+ |
# | | | |
# +----> D <----+
# | |
# +---+
#
# A import B, C
# B import D
# C import D
#
# $: python A.py gives
# - A.py
# - /home/tonyyang/Survey/cpython/experiment/B.pyc
# - /home/tonyyang/Survey/cpython/experiment/D.pyc
# + /home/tonyyang/Survey/cpython/experiment/D.pyc
# + /home/tonyyang/Survey/cpython/experiment/B.pyc
# - /home/tonyyang/Survey/cpython/experiment/C.pyc
# + /home/tonyyang/Survey/cpython/experiment/C.pyc
# + A.py