Python01

Java好久没看了,暂时放一放,先做实验。
简单回顾一下python知识。

数据类型

常见数据类型:整数、浮点数、字符串、布尔值、空值

整数

Python允许在数字中间以_分隔:1000_0000
运算:/:除法;//:地板除/整除;%:去余

  • 十进制:123
  • 二进制:0b1111011
  • 八进制:0o173
  • 十六进制:0x7b

浮点数

浮点数支持科学计数法:1.23e91.23e-8

字符串

''""括起来表示字符串。
转义字符:\
Python允许用r''表示''内部的字符串默认不转:

>>> print('\\\t\\')
\       \
>>> print(r'\\\t\\')
\\\t\\

可以用'''...'''表示多行文本:

print('''line1
line2
line3''')

# line1
# line2
# line3

布尔值

布尔值只有TrueFalse两个值。
常用逻辑运算:andornot

空值

空值用none表示

字符串和编码

字符集

常用编码:ASCII(1字节)、Unicode(2字节)、UTF-8(可变长:1-6字节)

字符ASCIIUnicodeUTF-8
A0100000100000000 0100000101000001
x01001110 0010110111100100 10111000 10101101

字符串

ord()函数获取字符的整数表示
chr()函数把编码转换为对应的字符

>>> ord('A')
65
>>> ord('中')
20013
>>> chr(66)
'B'
>>> chr(25991)
'文'

Python的字符串类型是str,在网络上传输,或者保存时,需要把str变为以字节为单位的bytes
encode()函数将str编码为指定的bytes
decode()函数把bytes转换为对应的str

>>> 'abc'.encode()
b'abc'
>>> '流樱'.encode()
b'\xe6\xb5\x81\xe6\xa8\xb1'
>>> b'abc'.decode()
'abc'
>>> b'\xe6\xb5\x81\xe6\xa8\xb1'.decode()
'流樱'

格式化输出

  1. 使用%占位符:%d:整数;%f:浮点数;%s:字符串;%x:十六进制整数
  2. 使用format()方法:使用{0}{1}占位,使用format()填入参数
    	>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
    	'Hello, 小明, 成绩提升了 17.1%'
    
  3. 使用f-string:以f开头的字符串,称为f-string,字符串中,就会替换为对应的变量
    	>>> name = '小明'
    	>>> print(f'hello {name}')
    	hello 小明
    

常用容器

  • list:是一种有序、可变的集合
    • append():在队尾添加元素
    • pop():删除队尾的元素
    • insert(inx, value):在指定的位置添加元素
  • tuple:是一种有序、不可变的集合
    • tuple的元素可以包含list
    • 定义只有1个元素的tuple时要加逗号,,消除歧义:(1,)
  • dict:是一种无序的键值对集合,查找速度快
    • 可以通过in判断key是否存在
    • get()方法,可以根据key获取值,若key不存在,可以返回None,或者指定的value:d.get('key', -1)
    • pop()方法,可以删除指定key对应的键值对
    • dict的key必须是不可变对象,list不能作为key
  • set:是一种无序、不重复的集合
    • set类似只存储key的dict,所以也不能存入可变对象(如list)
    • add()方法:添加元素
    • remove()方法:删除元素

流程控制

条件判断

ifelifelse

if a > 0:
    print(a)
elif:
    print(0)
else:
    print(-a)

循环

for...inwhile

names = ['Michael', 'Bob', 'Tracy']
for name in names:
    print(name)
sum = 0
n = 99
while n > 0:
    sum = sum + n
    n = n - 2
print(sum)

函数

定义函数

def 函数名(参数):

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x

pass

想定义一个什么事也不做的空函数,可以用pass语句:
pass可以用来作为占位符,还没想好怎么写函数的代码时,可以放一个pass,让代码能运行起来。

def nop():
    pass

pass还可以用在其他语句里,比如:

if age >= 18:
    pass

缺少了pass,代码运行就会有语法错误。

返回多值

python函数返回多个值时,使用tuple作为返回值。

>>> import math
>>> def quadratic(a,b,c):
...     x = -b
...     y = math.sqrt(b*b - 4*a*c)
...     z = 2*a
...     rst1 = (x + y) / z
...     rst2 = (x - y) / z
...     return rst1, rst2
... 
>>> print('quadratic(2, 3, 1) =', quadratic(2, 3, 1))
quadratic(2, 3, 1) = (-0.5, -1.0)
>>> print('quadratic(1, 3, -4) =', quadratic(1, 3, -4))
quadratic(1, 3, -4) = (1.0, -4.0)

函数的参数

  1. 位置参数:def power(x, n):pass
  2. 默认参数:def power(x, n=2):pass
    1. 默认参数可以简化函数的调用
    2. 必选参数在前,默认参数在后
    3. 默认参数必须指向不变对象
  3. 可变参数:def calc(*numbers):pass
    1. 传入的参数个数是可变的,可变参数会组装为一个tuple
    2. 在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:calc(*nums)
  4. 关键字参数:def person(name, age, **kw):pass
    1. 关键字参数允许传入0个或任意个含参数名的参数,关键字参数会组装为一个dict
    2. 在dict前面加两个*号,把dict的key-value变成关键字参数传进去:person('Jack', 23, **info)
    3. kw获得的dict是info的拷贝,对kw的改动不会影响到函数外的extra
  5. 命名关键字参数:def person(name, age, *, city, job):pass
    1. 用于限制关键字参数的名字,只接收city和job作为关键字参数,同时可以提供默认值
    2. 命名关键字参数需要特殊分隔符*,*后面的参数为命名关键字参数
    3. 如果函数定义中已经有了一个可变参数,后面的命名关键字参数就不再需要*了:def person(name, age, *args, city, job):pass
    4. 命名关键字参数必须传入参数名

参数组合

在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。
但是,参数定义的顺序必须是:
必选参数 > 默认参数 > 可变参数 > 命名关键字参数 > 关键字参数

def f1(a, b, c=0, *args, **kw):pass
def f2(a, b, c=0, *, d, **kw):pass

def mul(*args):
    if len(args) == 0:
        raise TypeError('no args')
    num = 1
    for arg in args:
        num *= arg
    return num

虽然可以组合多达5种参数,但不要同时使用太多的组合,否则函数接口的可理解性很差。

递归函数

递归函数:在函数内部调用自身本身的函数。
例如,可以用递归实现累加:

def sum(x):
    if x == 1:
        return 1
    return x + sum(x - 1)

递归函数的优点是定义简单,逻辑清晰。
理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

使用递归函数需要注意防止栈溢出。
解决递归调用栈溢出的方法是通过尾递归优化
尾递归:在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。
这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
使用尾递归优化累加函数:

def sum(n):
    return sum_iter(n, 0)

def sum_iter(num, product):
    if num == 0:
        return product
    return sum_iter(num - 1, num + product)

其中,return sum_iter(num - 1, num + product)仅返回递归函数本身。
num - 1num + product在函数调用前就会被计算,不影响函数调用。

递归经典:汉诺塔
思路:

  • 如果是1个盘子,直接将A柱子上的盘子从A移到C
  • 大于1个盘子:
    • 先将A柱子上的n-1个盘子借助C移到B
    • 直接将A柱子上的盘子从A移到C
    • 最后将B柱子上的n-1个盘子借助A移到C

实现:

def move(n, a, b, c):
    if n == 1:
        print(a, '-->', c)
    else:
        move(n-1, a, c, b)
        move(1, a, b, c)
        move(n-1, b, a, c)
tag(s): Python 
show comments · back · home