Intermediate Python Notes(中)

python  中的可变对象(mutuable)

  • 在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 __slots__魔法

在python的类,每次生成一个对象,都会生成一个保存类属性的字典__dict__,这样带来的

好处是:

  • 可以动态地增查改删属性。

缺点是:

  • 因为python不能在创建对象时指定分配内存的大小,所以如果创建成千上万个对象,就会消耗很多内存空间。

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)

<ipython-input-5-3778b53f416e> in <module>
      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__'

python中的collection包

  • defaultdict
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(<class 'list'>, {'banana': ['香蕉', '芭蕉'], 'orange': ['橘子', '柑子', '蜜橘']})
import json

print(json.dumps(fruit_alias))
{"banana": ["\u9999\u8549", "\u82ad\u8549"], "orange": ["\u6a58\u5b50", "\u67d1\u5b50", "\u871c\u6a58"]}
  • Counter 计数器
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})
  • deque 双端队列
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)

nametuples

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')])
  • enmu 枚举数据结构

注意的是,这个是在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

枚举 Enumerate

这里说的枚举和枚举类型不是一个东西,这里的枚举指的是枚举一个列表或序列。

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

python 中的自省

  • 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__', <class '__main__.TestClass'>), ('__delattr__', <method-wrapper '__delattr__' of TestClass object at 0x112940978>), ('__dict__', {'a': 1, 'b': 2}), ('__dir__', <built-in method __dir__ of TestClass object at 0x112940978>), ('__doc__', None), ('__eq__', <method-wrapper '__eq__' of TestClass object at 0x112940978>), ('__format__', <built-in method __format__ of TestClass object at 0x112940978>), ('__ge__', <method-wrapper '__ge__' of TestClass object at 0x112940978>), ('__getattribute__', <method-wrapper '__getattribute__' of TestClass object at 0x112940978>), ('__gt__', <method-wrapper '__gt__' of TestClass object at 0x112940978>), ('__hash__', <method-wrapper '__hash__' of TestClass object at 0x112940978>), ('__init__', <bound method TestClass.__init__ of <__main__.TestClass object at 0x112940978>>), ('__init_subclass__', <built-in method __init_subclass__ of type object at 0x7f98c185c1c8>), ('__le__', <method-wrapper '__le__' of TestClass object at 0x112940978>), ('__lt__', <method-wrapper '__lt__' of TestClass object at 0x112940978>), ('__module__', '__main__'), ('__ne__', <method-wrapper '__ne__' of TestClass object at 0x112940978>), ('__new__', <built-in method __new__ of type object at 0x10dff55e8>), ('__reduce__', <built-in method __reduce__ of TestClass object at 0x112940978>), ('__reduce_ex__', <built-in method __reduce_ex__ of TestClass object at 0x112940978>), ('__repr__', <method-wrapper '__repr__' of TestClass object at 0x112940978>), ('__setattr__', <method-wrapper '__setattr__' of TestClass object at 0x112940978>), ('__sizeof__', <built-in method __sizeof__ of TestClass object at 0x112940978>), ('__str__', <method-wrapper '__str__' of TestClass object at 0x112940978>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x7f98c185c1c8>), ('__weakref__', None), ('a', 1), ('add', <bound method TestClass.add of <__main__.TestClass object at 0x112940978>>), ('b', 2)]

Lambda 表达式

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)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值