在python中,列表是可变对象.每当你将一个变量赋值为另一个可变类型的变量时,对这个数据的任意改动会同时反映到这两个变量上去。新变量只不过是老变量的一个别名而已。
且在函数的参数中,默认参数只会运算一次!
foo=["abc"]
bar=foo
bar+=["666"]
print(bar)
print(foo)
['abc', '666']
['abc', '666']
def add_to(num,target=[]):
target.append(num)
return target
print(add_to(1))
print(add_to(2))
print(add_to(3))
[1]
[1, 2]
[1, 2, 3]
上面的定义函数方法是错误的,我们希望每次得到不同的结果
def add_to_2(num,target=None):
# 当传入的target参数为空时,会生成一个新的list
if target is None:
target=[]
target.append(num)
return target
print(add_to_2(1))
print(add_to_2(2))
print(add_to_2(3))
[1]
[2]
[3]
在python的类,每次生成一个对象,都会生成一个保存类属性的字典__dict__
,这样带来的
好处是:
缺点是:
slots魔法就是可以现式地指定所包含的属性,使用类slots的类对象就不会保存__dict__
属性字典。
class MyClass1(object):
def __init__(self,name,sex):
self.name=name
self.sex=sex
obj1=MyClass1("andy","male")
obj2=MyClass1("ann","female")
print(obj1.__dict__)
print(obj2.__dict__)
{'name': 'andy', 'sex': 'male'}
{'name': 'ann', 'sex': 'female'}
class MyClass2(object):
__slots__=["name","sex"]
def __init__(self,name,sex):
self.name=name
self.sex=sex
obj3=MyClass2("andy","male")
obj4=MyClass2("ann","female")
print(obj3.__dict__)
print(obj4.__dict__)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
in
8 obj3=MyClass2("andy","male")
9 obj4=MyClass2("ann","female")
---> 10 print(obj3.__dict__)
11 print(obj4.__dict__)
AttributeError: 'MyClass2' object has no attribute '__dict__'
from collections import defaultdict
fruit_name=[('banana',"香蕉"),('banana',"芭蕉"),('orange',"橘子"),('orange',"柑子"),('orange',"蜜橘")]
fruit_alias=defaultdict(list)
for name_eng,name_cn in fruit_name:
fruit_alias[name_eng].append(name_cn)
print(fruit_alias)
defaultdict(, {'banana': ['香蕉', '芭蕉'], 'orange': ['橘子', '柑子', '蜜橘']})
import json
print(json.dumps(fruit_alias))
{"banana": ["\u9999\u8549", "\u82ad\u8549"], "orange": ["\u6a58\u5b50", "\u67d1\u5b50", "\u871c\u6a58"]}
from collections import Counter
fruit_alias_cnt=Counter(name_eng for name_eng,name_cn in fruit_name)
print(fruit_alias_cnt)
Counter({'orange': 3, 'banana': 2})
from collections import deque
dq=deque()
dq.append(1)
dq.append("2")
dq.append("foo")
print(dq)
print("pop from left")
dq.popleft()
print(dq)
print("pop from right")
dq.pop()
print(dq)
print("append from left")
dq.appendleft(1)
print(dq)
print("append from right")
dq.append("foo")
print(dq)
deque([1, '2', 'foo'])
pop from left
deque(['2', 'foo'])
pop from right
deque(['2'])
append from left
deque([1, '2'])
append from right
deque([1, '2', 'foo'])
我们可以通过设置队列的最大长度,从而自动地从队首弹出和队尾退出。
dq2=deque(maxlen=8)
for i in range(8):
dq2.append(i)
print(dq2)
print("Be about to append 8 at right most!\n")
print("After reach max length of the deque, \
the left most element will be poped out automatically!\n")
dq2.append(8)
print(dq2)
deque([0, 1, 2, 3, 4, 5, 6, 7], maxlen=8)
Be about to append 8 at right most!
After reach max length of the deque, the left most element will be poped out automatically!
deque([1, 2, 3, 4, 5, 6, 7, 8], maxlen=8)
nametuple和tuple一样是不可变对象,可以通过下标索引来访问到具体的元素。
而nametuple又有点类似mini型的dict,可以像dict一样访问元素,但是是不可变的。
from collections import namedtuple
# 第一个参数是命名元组的名称,类似类的类名; 第二个参数是字段名称
student=namedtuple("Student","name stuNum sex")
andy=student(name="Andy",stuNum="123456",sex="male")
ann=student("Ann","123123","female")
print(andy)
print(ann.stuNum)
print(ann[2])
# 务必记住,nametuple是不可变对象(immutable)
# ann.sex="male" # ERROR!
andy_dict=andy._asdict() # 通过_asdict()将命名元组转化为字典,再改相应属性
andy_dict["stuNum"]=654321
print(andy_dict)
Student(name='Andy', stuNum='123456', sex='male')
123123
female
OrderedDict([('name', 'Andy'), ('stuNum', 654321), ('sex', 'male')])
注意的是,这个是在enum
包里的
from collections import namedtuple
from enum import Enum
class Species(Enum):
cat=1
dog=2
horse=3
# 但我们并不想关心同一物种的年龄,所以我们可以使用一个别名
kitten = 1 # (幼小的猫咪)
puppy = 2 # (幼小的狗狗)
# 可以用三种方式访问枚举类型的值
print(Species(2))
print(Species["cat"])
print(Species.horse)
print()
Animal=namedtuple("Animal","name age type")
perry=Animal(name="Perry",age=5,type=Species.dog)
kiyomi=Animal(name="Kiyomi",age=4,type=Species.puppy)
hello_kitty=Animal(name="Hello-Kitty",age=7,type=Species.kitten)
assert(perry.type==kiyomi.type)
print(hello_kitty.type)
Species.dog
Species.cat
Species.horse
Species.cat
这里说的枚举和枚举类型不是一个东西,这里的枚举指的是枚举一个列表或序列。
for idx,elemnt in enumrate(my_list):
print(idx,element)
my_list=["apple","banana","pear"]
# start 指示的是下表从哪个索引开始计算
for idx,ele in enumerate(my_list,start=1):
print(idx,ele)
1 apple
2 banana
3 pear
dir()
是Python中自省的最重要的函数之一,列举出当前对象的所有可用方法或当前作用域下的所有变量。
inspect
模块中也提供了getmembers()
函数来获取一个对象的所有成员函数。
my_list=[1,2,3,"bar","foo"]
print(dir(my_list))
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
# 不加参数,返回的是当前作用域内所有名字
print(dir())
['Animal', 'Enum', 'In', 'Out', 'Species', '_', '__', '___', '__builtin__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', '_dh', '_i', '_i1', '_i10', '_i11', '_i12', '_i13', '_i14', '_i15', '_i16', '_i17', '_i18', '_i19', '_i2', '_i20', '_i21', '_i22', '_i23', '_i24', '_i25', '_i26', '_i27', '_i28', '_i29', '_i3', '_i30', '_i31', '_i32', '_i33', '_i34', '_i35', '_i36', '_i37', '_i4', '_i5', '_i6', '_i7', '_i8', '_i9', '_ih', '_ii', '_iii', '_oh', 'andy', 'andy_dict', 'ann', 'deque', 'dq', 'dq2', 'ele', 'exit', 'get_ipython', 'hello_kitty', 'i', 'idx', 'kiyomi', 'my_list', 'namedtuple', 'perry', 'quit', 'student']
import inspect
class TestClass(object):
def __init__(self,a,b):
self.a=a
self.b=b
def add():
return self.a+self.b
test_case=TestClass(1,2)
print(inspect.getmembers(test_case))
[('__class__', ), ('__delattr__', ), ('__dict__', {'a': 1, 'b': 2}), ('__dir__', ), ('__doc__', None), ('__eq__', ), ('__format__', ), ('__ge__', ), ('__getattribute__', ), ('__gt__', ), ('__hash__', ), ('__init__', >), ('__init_subclass__', ), ('__le__', ), ('__lt__', ), ('__module__', '__main__'), ('__ne__', ), ('__new__', ), ('__reduce__', ), ('__reduce_ex__', ), ('__repr__', ), ('__setattr__', ), ('__sizeof__', ), ('__str__', ), ('__subclasshook__', ), ('__weakref__', None), ('a', 1), ('add', >), ('b', 2)]
lambda表达式是Python中的匿名函数,它是一个callable
的对象,原型为:
lambda param : operation(param)
add=lambda x,y : x+y
print(add(3,4))
7
# 列表排序
a = [(1, 2), (4, 1), (9, 10), (13, -3)]
a.sort(key=lambda x:x[1]) # 按照list中每个元素的第二个值进行排序
print(a)
[(13, -3), (4, 1), (1, 2), (9, 10)]