Python学习笔记
动机:
脚本可以省很多事情,
开发游戏用了lua,
但是,
真正日常要做一些东西脚本的时候,
发现用lua还是比较麻烦些,
所以,
就瞄上了python,
恩,
说学就学。
注意:
- 用的是Python3
- 适合有一定脚本语言基础的人看(很多脚本语言的共性没有记录)
基础
输出语句 print
注意多个参数的格式
1 | print('hello python!') |
list、tuple、dict、set
list 列表,有序的集合,随时添加删除元素
L = []
常用方法:
访问元素 - L[index] - index支持负数
末尾加入元素 - L.append(val)
某位置插入元素 - L.insert(index, val)
删除末尾元素 - L.pop()
删除某位置元素 - del L[index]tuple 元组,初始化后不可修改 [ 初始化一个元素的元组时,元素后要加, : t = (1, ) ]
T = ()
list 与 tuple 可相互嵌套,tuple中的list可以增删,因为存的是地址dict 字典(你也可以叫它map)
D = {‘key’: value, }set 集合,无序不重复
S = set([])
条件 与 循环
python的语法很简单,通过缩进来显示。
最重要的是:
1 | if <条件>: |
函数
1 | # 定义 |
当然,默认参数值,返回多个值,都是支持的
额外要注意的应该是 参数 部分,包括:必选参数、默认参数、可变参数、命名关键字参数、关键字参数。
可变参数允许传入0个或任意个参数,这些会被自动组装为一个tuple;
关键字参数允许传入0个或任意个含参数名的参数,这些被自动组装为1个dict。
1 | def book(name, author, **kw): |
PS:如果参数中已经有了一个可变参数,那么后面的命名关键字参数就不需要特殊分隔符’*‘了。
参数顺序: 必选参数、默认参数、可变参数、命名关键字参数、关键字参数。
1 | def f(a, b = 0, *args, **kw): # 必选参数、默认参数、可变参数、关键字参数 |
对于任意函数,都可以通过func(*args, **kw)的形式来调用它,无论参数是如何定义的。
其他
- range([start = 0,] stop, [, step = 1]]), 生成从start开始(默认为0)到stop(不等于stop),步长为step(默认为1)的整数序列;
start 与 step都是可选参数。
进阶
一些特性(切片、迭代、列表生成式、生成器)
切片
针对截取操作
L[start: stop: step]
截取从start序号开始到stop序号,步长为step的值成一个list返回。
1 | 10)) L = list(range( |
迭代
给定一个list或tuple,通过for循环来遍历它,这种遍历叫做 迭代(iteration)
很多语言的迭代是通过下标来进行的,但python里,并不是。
当然,顺序可能就不是你当初定义它时的顺序了。
1 | weekday = {'Mon': 1, 'Tue': 2, 'Wed': 3} |
isinstance(…, Iterable) 判断一个数据类型是否可迭代
一般可以可迭代对象是 集合数据类型(如 list、tuple、dict、set、str等),他们都是Iterable类型。
列表生成式
顾名思义,就是一个创建list的方式,
通过这种方式创建list比较便捷
1 | [x + y for x in 'ABC' for y in 'XYZ' if x != 'B'] |
生成器
针对于列表容量有限的缺陷,
生成器就是一边循环一边计算。
与列表生成式的区别是,列表生成时最外层是 [],而生成器最外层是 ()
而且,得到的generator,需要不停next得到下一个元素。(一般会通过for循环来迭代获取)
1 | g = (x + y for x in 'ABC' for y in 'XYZ' if x != 'B') |
可以作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列。
Iterator类型主要就两种,一种就是这个生成器,还有就是含yield的generator function
关于函数式编程 ( lambda、map、reduce、filter、 装饰器)
lambda [arg1 [, arg2, arg3, …]]: expression
也叫匿名函数,通过它可以非常方便快捷的定义使用一个函数。
具体效果,下面会给出。
map(func, seq1[, seq2…])
将func作用于seq中的每一个元素,并用一个列表给出返回值。
1 | def f(x): |
其实,用lambda更方便简洁
1 | m = map(lambda x: x*x, range(1, 6)) |
reduce(func, seq[, init])
这是一个二元操作函数,它用来将一个集合中所有数据进行从前到后的二元操作。
1 | from fuctools import reduce |
reduce要提前导入,
当然,也可以用lambda
1 | val = reduce(lambda x, y: x*10 + y, range(1, 6)) |
filter(func, seq)
可以当做过滤器,将集合中的每个数都传入函数,根据函数返回的bool变量来决定是否留下。
1 | def bigger_than_five(n): |
装饰器
装饰器的作用就像它名字一样,给函数以装饰,做一个更大一范围的修饰。
比如,有A、B、C三个果汁工厂,现在要在每瓶果汁上印一个小商标。
我们可以在每个工厂内建立一个流水线来印商标,
也可以专门建立一个工厂D来印商标。
装饰器,就像后者,工厂D。
1 | def myLog(func): |
注意要加语法糖 @装饰器函数
本装饰器的作用是在函数调用前输出一段log。
如果想让装饰器函数带参数,那就要进行三层嵌套。
1 | def myLog(logText): |
但是,这里的函数名已经发生了更改,demo名称其实已经发生了更改,
demo.__name__ 是 wrapper
可以通过加
wrapper.__name__ = func.__name__
来改回来,
但是,过于繁琐,python提供了更好的方法
1 | import functools |
关于面向对象编程
python中是有类这个结构的。
还有一些命名规则:
变量名以 _ 开头,代表私有变量(非强制)
变量名以 __ 开头,代表私有变量 (强制)
变量名以 __ 开头,并且以 __ 结尾,代表特殊变量
1 | class Person(object): |
也可以对实例进行一些属性的绑定,当然,不会对类造成影响。
当然也可以对类进行方法绑定,其所有的实例均受影响
1 | def set_height(self, height): |
最后,可以通过在类内设置一些函数来使类更加完善:
- __init__
初始化方法 - __slots__
设定允许绑定的变量名(子类会继承父类) - __len__
让类可以作用于len函数,设定计算类大小的方法 - __str__ 与 __repr__
都是用来当 print实例对象时 显示出来的字符串。
__str__是给用户看的,__repr__是给开发者看的(但一般都一样) - __iter__ 与 __next__
可以让类作用于 for…in 循环 - __getitem__
可以像list一样实现按照下标取元素 - __getattr__
预设某属性默认值 - __call__
实现在实例本身的调用方法。 - 装饰器实现get/set方法
1 | class Person(object): |
归纳
python的一些基础东西,基本就这些了。
接下来,就可以去做一些东西来边练手边加深理解。
最后,
工具是死的,
人是活得,
不要局限自己,
放飞思维,
大胆去做。
参考: