Python是动态语言,变量类型不固定;也是解释语言
Python的缺点:
源码不能加密,执行速度慢
直接在终端运行.py文件:
在.py文件头部加上 #!/usr/bin/env python3
在终端执行 chmod a+x hello.py 给文件执行权限
终端执行 ./hello.py 执行文件
输入输出
print("Hello world")
print(1+1)
print(a, b) #print多个参数,用空格连接
print('''line1
line2
line3''') #使用''' '''显示多行内容
print('%2d-%02d' % (3, 1)) # 格式('%d' % a)
print('%.2f' % 3.1415926) # %d是整形,%f浮点型,%s字符型
name = input() #输入
name = input('please enter your name: ') #带提示的输入
基础类型
3**2 # 3的2次方
#类型转换
float('1.9')
int(1.9)
right = True #布尔值:True False
none = None #空值用None表示,类似于nil
10 / 3 # == 3.33333, 得到一个浮点数
10 // 3 # == 3, 得到一个整数,类似于通常的整数除法
编码
ASCII编码是一个字节,只能显示少量字符
Unicode编码是两个字节,可以显示所有字符,用于显示
UTF-8是可变长度编码,根据字符决定编码长度,一般用于传输
# -*- coding: utf-8 -*- # 文件开头加这个表示使用utf-8编码,可以显示中文
ord('A') # 65
ord('中') # 20013, 获取字符十进制编码
chr(66) # B
chr(25991) # 文,将编码转换为字符
x = b'ABC' #b代表bytes类型
'ABC'.encode('ascii') # 用encode将字符串编码为指定的bytes
'中文'.encode('utf-8')
x.decode('ascii') # 用decode将bytes变为string
list和tuple
list中可以存放不同类型的成员
# list可变
classmates = ['A', 'B', 'C'] # 使用[]
len(classmates) # 使用len()获取长度,同样可对string使用
classmates[-1] # C, -1表示直接取最后一个元素
classmates[-2] # B, 取倒数第二个元素,以此类推
classmates.append('D') # 添加
classmates.insert(1, 'J') # 插入到位置1
classmates.pop() # 删除最后一个元素
classmates.pop(2) # 删除指定index的元素
classmates.remove('C') # 删除指定元素
# tuple初始化后不可变
classmates = ('A', 'B', 'C') # 不可修改
t = (1,) # 定义一个元素的tuple最后加逗号
newClassmates = classmates # 这里没有创建新list,newClassmates和classmates共享内存(类似C++指针)
newClassmates = classmates[:] # 使用切片复制list
newClassmates = list(classmates) # 使用list()复制list
条件判断
age = 3
if age > 18: # 注意冒号
print('Adult') # 注意缩进
elif age >= 8: # else if写作elif
print('Teenager')
else:
print('Infancy')
if age < 100
pass # 表示什么都不做
if num in nums: # 元素在list中
if name not in names: # 元素不在list中
if a < b and c > d: # 与
if a < b or c >d: # 或
循环
names = ['A', 'B', 'C', 'D']
for name in names: # 使用:
print(name)
for x in range(100) : # range(x)生成0到x-1的整数序列
x += x
while n >0:
print('xxx')
字典和集合
d = {'A': 95, 'B': 100, 'C': 60}
#判断key是否存在
'D' in d # False
d.get('D') # 返回None
d.pop('key') # 删除
#set
s = set([1,2,3,4]) # 使用一个list来初始化
s.add(5) # 添加元素
s.remove(3) # 删除元素
函数
def my_abs(x): # 使用def定义函数,不需要返回类型
if not isinstance(x, (int, float)): # 使用isinstance进行参数检查
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
def empty():
pass # 空函数
# 返回多个返回值
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny # 返回的实际是一个tuple
# 可变参数
def calc(*numbers): # 参数前加*
sum = 0
for n in numbers: # 实际接受到的是一个tuple
sum = sum + n * n
return sum
calc(1,2,3) # 直接调用
nums = [1, 2, 3]
calc(*nums) # 通过list调用
# 关键字参数
def person(name, age, **kw): # 使用**表示任意个含参数名的参数
print('name:', name, 'age:', age, 'other:', kw)
person('Bob', 35, city='Beijing') # 直接调用
person('Adam', 45, gender='M', job='Engineer') # name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra) # 通过list调用, name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
def person(name, age, *, city, job): # 只接受city和job关键字的参数
print(name, age, city, job)
def person(name, age, *args, city, job): # 如果有可变参数,可以不写*
print(name, age, city, job)
# 参数定义顺序
def f1(a, b, c=0, *args, d, **kw): # 必选参数,默认参数,可变参数,命名关键字参数(d),关键字参数
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
递归
每一层递归会占用一层栈,递归过多会导致栈溢出,使用尾递归可能可以解决此问题(如果编译器作过优化,python编译器没有)
def fact(n):
return fact_iter(n, 1)
def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product) # 尾递归,返回递归函数本身,不含其他运算
切片
可用于list, tuple, string
L = [1,2,3,4,5]
L[0:3] # [1,2,3] 可以看作 0..<3
L[:3] # [1,2,3]
L[1:3] # [2,3]
L[-2:] # [4,5]
L[-2:-1] # [4]
L = list(range(100)) # 从range创建list
L[:10:2] # [0,2,4,6,8]
L[::5] # [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
迭代
isinstance('abc', Iterable) # 判断变量是否可迭代
# dict迭代
d = {'a': 1, 'b': 2, 'c': 3}
for key in d: # 默认迭代key
pass
for value in d.values(): # 迭代value
pass
for k, v in d.items(): # 同时迭代key和value
pass
for i, value in enumerate(['A', 'B', 'C']): # enumerate()函数同时返回index和值
print(i, value)
列表生成式
list(range(1, 11)) # [1,2,...9,10]
[x * x for x in range(1, 11)] # x平方组成的list,[1,4,9,...,81,100]
[x * x for x in range(1, 11) if x % 2 == 0] # for循环接判断条件,[4,16,36,64,100]
[m + n for m in 'ABC' for n in 'XYZ'] # 两层循环全排列,[AX,AY,AZ,BX,...CY,CZ]
生成器(generator)
一边循环一边计算,这样可以只访问前面一定数量的元素。把[ ]改成( )
L = [x * x for x in range(10)] # 列表生成式
g = (x * x for x in range(10)) # 生成器、
next(g) # 打印g的下一个元素
for n in g: # 使用for循环遍历g
print(n)
# 定义生成器
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b # 使用yield关键字,执行时遇到yield返回,下次执行从yield处开始
a, b = b, a + b
n = n + 1
return 'done'
迭代器(Iterator)
Iterator和Iterable是两个东西。
能被for循环迭代的是Iterable,如list,tuple。
能调用next()的是Iterator,如generator。Iterator是惰性的,初始时可能不知道长度,在需要返回下一个数据时才进行计算。
isinstance(iter('abc'), Iterator) # 使用iter()将Iterable转化为Iterator
# 迭代器循环
it = iter([1, 2, 3, 4, 5])
while True:
try:
# 获得下一个值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循环
break
函数式编程
python中可以将函数作为一种类型(类似C++函数指针)
# 高阶函数
def add(x, y, f): # 传入参数有函数
return f(x) + f(y)
print(add(-5, 6, abs))
#map函数
def f(x):
return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) # 传入一个函数和一个list,让函数作用于每个元素,并返回一个新list
list(r) # r是Iterator,使用list()转成list
#reduce,传入一个函数和一个list,reduce把函数计算结果和list后面的元素进行累积计算
def fn(x, y): # 传入reduce的函数接受两个参数
return x * 10 + y
reduce(fn, [1, 3, 5, 7, 9]) # 13579
#map reduce 版string to int
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def char2num(s):
return DIGITS[s]
def str2int(s):
return reduce(lambda x, y: x * 10 + y, map(char2num, s)) # map将s转换成int list,reduce再将list元素组成一个数字
filter
接受一个函数和一个list,对每个list元素执行函数,根据返回True或者False将结果放入输出list中
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # [1, 5, 9, 15]
sorted
sorted([36, 5, -12, 9, -21], key=abs) # key参数代表排序方法
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True) # reverse参数代表反向排序
students = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
sorted(students, key=itemgetter(0)) # 根据第一个参数排序
sorted(students, key=itemgetter(1)) # 根据第二个参数排序
f = itemgetter(2) # 获取第3个元素
f(students) # students[2]
函数高级用法
# 函数作为返回值
# 返回函数不要引用任何循环变量,或者后续会发生变化的变量!
def lazy_sum(*args):
def sum(): # sum可以使用外部参数,闭包
ax = 0
for n in args:
ax = ax + n
return ax
return sum # 返回时,相关参数和变量会保存在sum中
f = lazy_sum(1, 3, 5, 7, 9) # 此时不计算求和
f() # 实际进行求和
# lambda函数
# lambda x: x*x, 使用lambda关键字,冒号前面是参数,后面是表达式,返回结果为表达式结果
list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
# 装饰器
def log(func): # 定义装饰器
# 将func的__name__赋值给wrapper
@functools.wraps(func)
def wrapper(*args, **kw): #(*args, **kw)表示可以传入任何参数
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now(): # 使用装饰器,等价于now = log(now)
print('2015-3-25')
# 偏函数
# 把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数比调用原函数更简单
int2 = functools.partial(int, base=2) # int2 = int(x, base = 2)
int2('1000000')
模块
Python中,一个py文件就称为一个模块
每个文件夹称为一个包,包中必须有init.py文件
#!/usr/bin/env python3 # 可以在linux上直接执行
# -*- coding: utf-8 -*- # 使用utf-8编码
' a test module '
__author__ = 'Michael Liao' # 文件作者
import sys # 导入模块
def test():
args = sys.argv
if len(args)==1:
print('Hello, world!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
def _private_1(name): # 私有变量、函数名以_开头(实际上可访问,只是约定)
return 'Hello, %s' % name
if __name__=='__main__': # 在命令行运行时会进入这个判断,可用于测试
test()
面向对象编程
# 声明一个类
class Student(object): # 使用class关键字,括号内表示父类,没有父类则继承object类
count = 0 # 类属性,所有实例都能访问
def __init__(self, name, score): # 使用__init__定义构造函数,第一个参数为self
self.name = name # 类内不用声明成员变量,直接使用
self.__score = score # __开头表示私有成员
def print_score(self): # 成员函数第一个参数为self
print('%s: %s' % (self.name, self.score))
bart = Student('Bart Simpson', 59)
bart.age = 8 # 在外部给实例添加成员
动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的
class Animal(object): # 基类
def run(self):
print('Animal is running...')
class Dog(Animal): # 子类
def run(self):
print('Dog is running...')
class Timer(object): # 鸭子类型(不是Animal,但实现了run( ))
def run(self):
print('Start...')
def run_twice(animal):
animal.run()
animal.run()
run_twice(Animal())
run_twice(Dog())
run_twice(Timer()) # 只要实现了run(), 便可传入执行
辅助方法
type(1) # 获取类型
isinstance(1, int) # 等效于type()
isinstance(dog, Dog) # 判断class
dir(dog) # 获得对象的所有属性和方法
hasattr(dog, 'x') # 判断dog是否有属性x, 对函数同样适用
getattr(dog, 'x') # 获得属性x,如果没有抛出AttributeError
getattr(dog, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
setattr(dog, 'y', 19) # 设置一个属性'y',如果有就修改,没有就新建
高级面向对象
# 动态给类添加函数
def set_score(self, score):
self.score = score
Student.set_score = set_score
from types import MethodType # 给类添加
s.set_age = MethodType(set_age, s) # 给实例添加
# __slots__
class Student(object):
__slots__ = ('name', 'age') # 限制类只能添加name和age属性(仅对本身起效,子类不影响)
# @property # 将方法变成属性
class Student(object):
@property # getter
def birth(self):
return self._birth
@birth.setter # setter
def birth(self, value):
self._birth = value
@property # 只读属性
def age(self):
return 2015 - self._birth
s = Student()
s.birth = 2010
age = s.age
# 多重继承
class Bat(Mammal, Flyable): # 括号中写所有父类
pass
定制类
# __str__() 用于print
class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object (name: %s)' % self.name
__repr__ = __str__ # __repr__用于直接显示,一般设为等于__str__
def __call__(self): # 直接调用实例
print('My name is %s.' % self.name)
print(Student('Michael')) # 此时调用__str__
s = Student()
s # 此时调用__repr__
s() # 此时调用__call__
# __iter__, 用于允许遍历
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b
def __iter__(self):
return self # 实例本身就是迭代对象,故返回自己
def __next__(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 100000: # 退出循环的条件
raise StopIteration()
return self.a # 返回下一个值
def __getitem__(self, n):
if isinstance(n, int): # n是索引
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
if isinstance(n, slice): # n是切片
start = n.start
stop = n.stop
if start is None:
start = 0
a, b = 1, 1
L = []
for x in range(stop):
if x >= start:
L.append(a)
a, b = b, a + b
return L
for n in Fib(): # 不断调用__next__
print(n)
Fib()[10] # 此时调用__getitem__
Fib[:10] # 调用切片
枚举
from enum import Enum, unique
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) # name + members
for name, member in Month.__members__.items(): # __members__获取成员
print(name, '=>', member, ',', member.value)
@unique # @unique关键字检查每个元素的唯一性
class Weekday(Enum):
Sun = 0 # Sun的value被设定为0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
错误处理
错误是class
try: # 使用try来捕获函数
print('try...')
r = 10 / 0
print('result:', r)
except ValueError as e: # 如果抛出ValueError执行以下代码
print('ValueError:', e)
except ZeroDivisionError as e:
print('except:', e)
finally: # 最后执行以下代码(不管抛不抛出错误都会执行)
print('finally...')
with open('/path/to/file', 'r') as f: # 等效于try
print(f.read())
使用assert或logging
$ python -O err.py # 命令行启动时-o关闭assert
assert n != 0, 'n is zero!' # 如果 n==0,抛出错误
s = '0'
n = int(s)
logging.info('n = %d' % n) # logging不抛出错误,而是存在文件里
IO操作
f = open('/Users/michael/test.txt', 'r') # r表示读,如果失败,抛出IOError
f.read() # 读取文件的全部内容
f.read(size) # 读取一定size的内容
f.readline() # 读取一行内容
f.readlines() # 按行读取内容,返回list
f.close() # 关闭文件
f = open('/Users/michael/test.jpg', 'rb') # rb表示读取二进制文件
f.read()
f = open('/Users/michael/test.txt', 'w') # w代表写文件
f.write('Hello, world!')
f.close()
StringIO 在内存中读写str
BytesIO 在内存中读写二进制文件
操作文件夹
os.path.abspath('.') # 查看绝对目录
os.path.join('/Users/michael', 'testdir') # 拼接目录
os.mkdir('/Users/michael/testdir') # 创建一个目录
os.rmdir('/Users/michael/testdir') # 删掉一个目录
pickling,持久化存储
d = dict(name='Bob', age=20, score=88)
f = open('dump.txt', 'wb')
pickle.dump(d, f) # 将d写入f
c = pickle.load(f) # 从f中读入数据
f.close()
#json
json.dumps(d) # 将d储存为json格式
json_str = '{"age": 20, "score": 88, "name": "Bob"}'
json.loads(json_str) # 读取json内容
def student2dict(std):
return {
'name': std.name,
'age': std.age,
'score': std.score
}
print(json.dumps(s, default=student2dict)) # 传入自定义方法序列化class
print(json.dumps(s, default=lambda obj: obj.__dict__)) # __dict__将对象转化为dict
常用内建模块
datetime
from datetime import datetime # 有datetime模块和datetime类
now = datetime.now() # 获取当前时间
dt = datetime(2015, 4, 19, 12, 20) # 创建指定时间
dt.timestamp() # 将datetime转换为timestamp,1429417200.0
toDt = datetime.fromtimestamp(t) # 将timestamp转换为datetime(本地时间)
cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S') # str转换为datetime
cday.strftime('%a, %b %d %H:%M') # datetime转换为str
collections
# namedtuple
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y']) # 命名的tuple
p = Point(1, 2) # 像类一样使用
p.x
# deque 双向链表
q = deque(['a', 'b', 'c'])
q.appendleft('y') # 插入头部
q.popleft() # 删除头部
# OrderedDict 按照key插入的顺序排序
od = OrderedDict([('b', 2), ('c', 3), ('a', 1)]) # od = [b..,c..,a..]
装饰器
装饰器的本质是赋值
def use_logging(func):
def wrapper():
logging.warn("%s is running" % func.__name__)
return func() # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()
return wrapper
def foo():
print('i am foo')
foo = use_logging(foo) # 因为装饰器 use_logging(foo) 返回的时函数对象 wrapper,这条语句相当于 foo = wrapper
foo()
@use_logging # 等价于foo = use_logging(foo)
def foo1():
print("i am foo1")
foo1()
class Foo3(object):
def __init__(self, func):
self._func = func
def __call__(self):
print ('class decorator runing')
self._func()
print ('class decorator ending')
@Foo3 #类装饰器
def bar():
print ('bar')
bar() #调用__call__
网友评论