语言相关问题

引用谜题

# inmutalbe object
x = 42
y = x
x = x + 1
print(x)
print(y)

# mutable object
x = [1, 2, 3]
y = x
x[0] = 4
print(x)
print(y)

# Copy quiz
x = ['foo', [1, 2, 3], 10.4]
y = list(x)  # or x[:] copy
y[1][0] = 4
print(x)
print(y)

# Copying objects
# Trickier with mutable objects
# You have a list `a` you wish to copy to `b`
# Creating an alias not a copy
b = a  # a == b and a is b [id(a) == id(b)]
# Creating a shallow copy (all objects inside are aliases!)
b = a[:]  # a == b but a is not b
# Creating a deep copy (all objects inside are copies)
# Use the deepcopy() function in the copy module
b = copy.deepcopy(a)

类属性

# Question 1

class C:
    name = 'foo'

c1 = C()
c2 = C()
c2.name = 'bar'
C.name = 'foo'
print('{}, {}, {}'.format(c1.name, c2.name, C.name))

# Question 2
class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)

"""
The key to the answer is that, in Python, class variables are internally handled as dictionaries.
If a variable name is not found in the dictionary of the current class, the class hierarchy (i.e.,
its parent classes) are searched until the referenced variable name is found (if the referenced
variable name is not found in the class itself or anywhere in its hierarchy, an AttributeError occurs).
"""

闭包变量值的问题

def create_multipliers():
    return [lambda x: i * x for i in range(4)]
r = [m(2) for m in create_multipliers()]
# r 的结果是?
# 如何避免?
# 这其中的奥妙在于 lambda 表达式中的 i 是一个自由变量, 在运行时绑定值,而不是定义时就绑定,
# 这跟函数的默认值参数定义是不同的。 因此,在调用这个 lambda 表达式的时候,i 的值是执行时的值。
>>> [lambda x: i*x for i in range(4)]
... [<function __main__.<listcomp>.<lambda>(x)>,
     <function __main__.<listcomp>.<lambda>(x)>,
     <function __main__.<listcomp>.<lambda>(x)>,
     <function __main__.<listcomp>.<lambda>(x)>]
>>> [lambda x, i=i: i*x for i in range(4)]
... [<function __main__.<listcomp>.<lambda>(x, i=0)>,
     <function __main__.<listcomp>.<lambda>(x, i=1)>,
     <function __main__.<listcomp>.<lambda>(x, i=2)>,
     <function __main__.<listcomp>.<lambda>(x, i=3)>]

# The reason for this is that Python’s closures are late binding.
# This means that the values of variables used in closures are looked up at the time the inner function is called.
# So as a result, when any of the functions returned by multipliers() are called, the value of i is looked up in the surrounding scope at that time.
# By then, regardless of which of the returned functions is called, the for loop has completed and i is left with its final value

# 解决方法 0
def multipliers():
    return (lambda x : i * x for i in range(4))

# 解决方法 1
def multipliers():
    return [lambda x, i=i : i * x for i in range(4)]

# 解决方法 2
def multipliers():
    for i in range(4): yield lambda x : i * x

# 解决方法 3
from functools import partial
from operator import mul

def multipliers():
    return [partial(mul, i) for i in range(4)]

# 以下方法可以获取函数定义的默认签名参数
def func(a=1):
    pass
import inspect
s = inspect.signature(func)
# <Signature (a=1)>
# 注意匿名函数 `:` 号前为函数参数 `:` 后为函数体
print(inspect.signature(lambda x: x*2))
print(inspect.signature(lambda x=3: x*2))

迭代进行时修改列表

odd = lambda x: bool(x % 2)
numbers = [n for n in range(10)]
for i in range(len(numbers)):
    if odd(numbers[i]):
        # BAD: Deleting item from a list while iterating over it
        del numbers[i]

Traceback (most recent call last):
           File "<stdin>", line 2, in <module>
IndexError: list index out of range

# 如果要得到期望结果可以使用列表推导式
numbers[:] = [n for n in numbers if not odd(n)]  # beauty

变量作用域***

>>> x = 10
>>> def foo():
...     x += 1
...     print(x)
>>> foo()   # 执行结果是什么?

>>> def bar():
...     global x
...     x += 1
...     print(x)
>>> bar()   # 执行结果是什么?

# 使用 list 做局部变量
>>> lst = [1, 2, 3]
>>> def foo1():
...     lst.append(5)    # this is work
... foo1()
>>> lst
# lst 的结果是?

>>> lst2 = [1, 2, 3]
>>> def foo2():
...     lst += [5]   # bombs!!!
>>> foo2()  # 运行结果是?

类型属性查找

class A(object):
    x = 1

class B(A):
    pass

class C(A):
    pass

print(A.x, B.x, C.x)  # what's the output?

B.x = 2
print(A.x, B.x, C.x)  # what's print now?

A.x = 3
print(A.x, B.x, C.x)  # And now what output?

函数默认值初始化

def foo(bar=[]):
    bar.append('baz')
    return '%s, %i' % (bar, id(bar))

>>> foo()
"['baz'], 4318961736"
>>> foo()
"['baz', 'baz'], 4318961736"
>>> foo()
"['baz', 'baz', 'baz'], 4318961736"
# 每次调用 foo(), bar使用同一个 list 对象,修改如下
def foo(bar=None):
    if bar is None:
        bar = []
    bar.append('baz')
    return bar
>>> foo()
['baz']
>>> foo()
['baz']

# 以下代码的输出结果
def extendList(val, lst=[]):
    lst.append(val)
    return lst
a = extendList(10)
print('first:', a)
b = extendList(123,[])
c = extendList('a')
print('second:', a)
print('b': b)
print('c': c)
# first: [10]
# second: [10, 'a']
# b: [123]
# c: [10, 'a']

按规则给一组数字排序

# 正数在前,负数在后;正数从小到大,负数从大到小le
lst = [5, 0, -1, 3, -2, -5, -10, 9, 8, 3]
expected = [0, 3, 3, 5, 8, 9, -1, -2, -5, -10]
# 方法1:
r = sorted(lst, key=lambda x: (x<0, x if x >= 0 else -x))
# 方法2:
r = sorted(x for x in lst if x >=0) + sorted((y for y in lst if y < 0), reverse=True)
# or
r = sorted(x for x in lst if x >=0) + sorted((y for y in lst if y < 0), key=lambda x: -x)

Beautiful use case of enumerate()

def polynomial(x, coefficients):
    return sum(c * x ** i for (i, c) in enumerate(coefficients))
r = polynomial(2, [10, 3, 4])

表达式区别

  • [x * 2 for x in lst]
  • (x * 2 for x in lst)
  • {x * 2 for x in lst}

概念和一些好的问题

  1. 浏览器输入 URL 后到服务器,最后生产页面整个过程按时间序列描述操作关键词语
  2. lst 是一个 list 对象,lst.insert(0, x)lst.append(x) 的算法复杂度
  3. Python socket 编程

切片

lst = ['a', 'b', 'c', 'd', 'e']
# 输出结果
print(lst[10:])

"""
The above code will output [], and will not result in an IndexError.

As one would expect, attempting to access a member of a list using an index
that exceeds the number of members (e.g., attempting to access list[10] in
the list above) results in an IndexError. However, attempting to access a
slice of a list at a starting index that exceeds the number of members in
the list will not result in an IndexError and will simply return an empty list.

What makes this a particularly nasty gotcha is that it can lead to bugs
that are really hard to track down since no error is raised at runtime.
"""

列表推导

Given a list of N numbers, use a single list comprehension to produce a new list that only contains those values that are:

  1. even numbers, and
  2. from elements in the original list that had even indices
# Input
# Index 0   1   2   3    4    5    6    7    8
lst = [ 1 , 3 , 5 , 8 , 10 , 13 , 18 , 36 , 78 ]
[x for x in list[::2] if x%2 == 0]
# Output
[10, 18, 78]

字典

class DefaultDict(dict):
    def __missing__(self, key):
        return []

# What is the output?
d = DefaultDict()
print(d)
d['florp'] = 127
print(d)
print(d['foo'])

# Here is a `__missing__`-based method that will update the dictionary, as well as return a value
class DefaultDict(dict):
    def __missing__(self, key):
        newval = []
        self[key] = newval
        return newval