前置文字部分几乎都refer自www.liaoxuefeng.com/

笔记用,来自:www.liaoxuefeng.com/和蟒蛇书,自用非原创

python中的一些语法细节

  1. 2**10 = pow(2,10); = 1024

  2. a+b = 在没有做int处理的话,经常会发生字符串相加的情况,比如若a=3,b=1则a+b输出31

  3. print()会依次打印每个字符串,遇到逗号“,”会输出一个空格

  4. Python允许在数字中间以_分隔

  5. “”或者‘’都可以包含字符串

  6. 转义字符和c类似' "都可以用来输出’ “等

  7. 如果字符串内部有很多换行,用\n写在一行里不好阅读,为了简化,Python允许用’’’…’’’的格式表示多行内容

  8. 布尔值和布尔代数的表示完全一致,一个布尔值只有True、False两种值,要么是True,要么是False,在Python中,可以直接用True、False表示布尔值(请注意大小写),也可以通过布尔运算计算出来

  9. 这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如Java是静态语言

  10. 在Python中,通常用全部大写的变量名表示常量:PI = 3.14159265359

  11. /除法计算结果是浮点数,即使是两个整数恰好整除,结果也是浮点数,还有一种除法是//,称为地板除,两个整数的除法仍然是整数

  12. %和c相同

  13. Python的整数没有大小限制,而某些语言的整数根据其存储长度是有大小限制的,例如Java对32位整数的范围限制在-2147483648-2147483647

  14. Python的浮点数也没有大小限制,但是超出一定范围就直接表示为inf(无限大)。

python的编码

UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件:

对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符:
如果知道字符的整数编码,还可以用十六进制这么写str:
print(‘\u4e2d’’\u6587’)
‘中文’

以Unicode表示的str通过encode()方法可以编码为指定的bytes
如果bytes中包含无法解码的字节,decode()方法会报错

要计算str包含多少个字符,可以用len()函数:

由于Python源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为UTF-8编码。当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;

第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。

申明了UTF-8编码并不意味着你的.py文件就是UTF-8编码的,必须并且要确保文本编辑器正在使用UTF-8 without BOM编码:

在Python中,采用的格式化方式和C语言是一致的,用%实现

%d 整数
%f 浮点数
%s 字符串
%x 十六进制整数
%% %作为转义字符使用输出结果为%

format()
另一种格式化字符串的方法是使用字符串的format()方法,它会用传入的参数依次替换字符串内的占位符{0}、{1}……,不过这种方式写起来比%要麻烦得多:

>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成绩提升了 17.1%'

continue语句的作用是结束本次循环

set
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。

要创建一个set,需要提供一个list作为输入集合:

>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}

注意,传入的参数[1, 2, 3]是一个list,而显示的{1, 2, 3}只是告诉你这个set内部有1,2,3这3个元素,显示的顺序也不表示set是有序的。。

重复元素在set中自动被过滤:

set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:

>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}

不可变对象, 有关对其的论述见廖雪峰使用dic和set的一节

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
print("goodness")
print("hello","do you like van","van you see?")
# print("a =")
# a = input()
# print("b =")
# b = input()
# c = a+b
# print("a+b is",c)
print('''line1
line2
line114514''')
3>5
print(3>5)
print(1>6 and 3< 5)
print("全世界都在说中国话")
print('\u4e2d')
ch  =  'are you fine?'
kr = 1.412
print("How are you %s %s you score is %.1f rank up %d" % ('bert',ch,kr,-1) )
name  = '我觉得这就是一种自信'
print(f"fuck you {name} {kr:.2f}")
print(2**10)
r = 1.442
print('{}成绩提升为{}'.format('小明',r))
classmates = [1,2,'你好']
print(classmates[0])
print(classmates[1])
print(classmates[2])
print(classmates[-1])
print(classmates[-2])
print(classmates[-3])
print(len(classmates))
classmates2 = (1,2,[9,5,4])
print(classmates2[1])
print(classmates2[2,1])
classmates2[2,1] = '变'
print(classmates2[2,1])
t = ("你妈的电脑",)
print(t)

输出

goodness
hello do you like van van you see?
line1
line2
line114514
False
False
全世界都在说中国话
中
How are you bert are you fine? you score is 1.4 rank up -1
fuck you 我觉得这就是一种自信 1.41
1024
小明成绩提升为1.442
1
2
你好
你好
2
1
3
2
5
变
('你妈的电脑',)

# -*- coding: utf-8 -*-
t = [[1],[2],['大','f']]
print(t[2][1])# 2 dimension vector
kr = (1,2,['你好','世界'])
for x in range(3): #from interge 0 to 2, number 3 tuple overflowed
    print(kr[x])
#kr[1] = 5 #TypeError: 'tuple' object does not support item assignment
#print(kr[1])
kr[2][1] = '去死吧'#tuple 里面的 list的元素可以修改
for x in range(3):
    print(kr[x])
print(t)
l = t[1] + t[0]
print(l) 
l = t[1][0] + t[0][0]
print(l)
l = int(t[1][0])+int(t[0][0])
print(l)
l = float(t[1][0])+int(t[0][0])#datatype transformation
print('%.1f' % (l))
l = float(t[1][0])+float(t[0][0])
print('%.1f' % (l))
print('len = %d' % (len(t)))
t.pop()
print('t = ',t)#尾部的整个数组直接弹出
print('len = %d' % (len(t)))
t.append('鸡你实在是太美')#尾部增加一个字符串
t.pop(0)#下标为0的元素弹出
print(t)
print('len = %d' % (len(t)))
t.append('鸡你实在是太美')
print(t)
print(t.count('鸡你实在是太美'))#统计相同字符串的个数
t.reverse()#反转了
print(t)
L = ()
print(len(L))#创建了一个长度为0的tuple

输出

f
1
2
['你好', '世界']
1
2
['你好', '去死吧']
[[1], [2], ['大', 'f']]
[2, 1]
3
3
3.0
3.0
len = 3
t =  [[1], [2]]
len = 2
[[2], '鸡你实在是太美']
len = 2
[[2], '鸡你实在是太美', '鸡你实在是太美']
2
['鸡你实在是太美', '鸡你实在是太美', [2]]
0

# -*- coding: utf-8 -*-
names = ['Michael', 'Bob', 'Tracy']
for name in names:
    print(name)
    sum = 0
for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
    sum = sum + x
print(sum)
l = ['蔡徐坤','谷爱凌','瑞克.丁真','尼古.丁真','你好','卢本伟没有被输出']
for x in l:
    if(x == '你好'): 
        print('撒由那拉嘞baby')
        break
    elif(x != '谷爱凌'):
        print('你好,',x,'先生')
        continue
    else: print('{}你是一个一个一个一个双国籍人士啊'.format(x))

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
print(d['Michael']) #可以理解为enum,map,用字符串当作下标的数组
#底层大概是用哈希表实现的是一种空间换时间的策略
print('Thomas' in d)
k = d.get('你妈的电脑')
print(k)

输出:

Michael
Bob
Tracy
55
你好, 蔡徐坤 先生
谷爱凌你是一个一个一个一个双国籍人士啊
你好, 瑞克.丁真 先生
你好, 尼古.丁真 先生
撒由那拉嘞baby
95
False
None

函数

max函数max()可以接收任意多个参数,并返回最大的那个

>>> max(1, 2)
2
>>> max(2, 3, 1, -5)
3

数据类型转换
Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数:

>>> int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> str(100)
'100'
>>> bool(1)
True
>>> bool('')
False
# -*- coding: utf-8 -*-
def adding(a , b , c = 3):#c为可变参数
    if(a > b): print('a大于b')
    elif(a == b): print('a等于b')
    else: print('a小于b')
    print('c = ',c)
    return
###############################
a = int(input())
b = int(input())
adding(a,b,2)

def add_end(l = None):
    if(l == None):
        l = []
    l.append('END')
    return

def add_end2(l = []):
    l.append('END')
    print(l)
    return
###############################
l = [1,3,'你舍得打破这份宁静吗']
add_end(l)
print(l)
l = []
add_end(l)
print(l)
l = []
add_end(l)
print(l)

add_end2()
add_end2()

输出

1
2
a小于b
c =  2
[1, 3, '你舍得打破这份宁静吗', 'END']
['END']
['END']
['END']
['END', 'END']

Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

可变参数

在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。

我们以数学题为例子,给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……。

要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c……作为一个list或tuple传进来,这样,函数可以定义如下:

def calc(numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

但是调用的时候,需要先组装出一个list或tuple:

>>> calc([1, 2, 3])
14
>>> calc((1, 3, 5, 7))
84

如果利用可变参数,调用函数的方式可以简化成这样:

>>> calc(1, 2, 3)
14
>>> calc(1, 3, 5, 7)
84

所以,我们把函数的参数改为可变参数:

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:

>>> nums = [1, 2, 3]
>>> calc(nums[0], nums[1], nums[2])
14

这种写法当然是可行的,问题是太繁琐,所以Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:

>>> nums = [1, 2, 3]
>>> calc(*nums)
14

isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。

目前为止,我们使用函数时所用的参数都是位置参数,即传入函数的实际参数必须与形式参数的数量和位置对应。而本节将介绍的关键字参数,则可以避免牢记参数位置的麻烦,令函数的调用和参数传递更加灵活方便。

关键字参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict

# -*- coding: utf-8 -*-
def ID(name, age, **kw):
    if 'job' in kw :#检测kw里是否有关键字job
        print('你好')
        pass
    print('name = ',name,'age = ',age,'other information = ',kw)

ID('brown',14)
ID('dick',12,city = 'New York')
ID('Mary',14,gender = 'female')
ID('Jerry',16,city = 'sydney',country = 'australia')
ID('Frank',24,job = 'actor',zipcode = 123456)
extra = {'worksite' : 'hospital', 'city' : 'beijing'}
ID('Linawei',18,worksite = extra['worksite'],city = extra['city'])

def person(name, age, *, city = 'osaka', job):
    print(name,age,city,job)

person('shit',32,city = 'tokyo',job = 'singer')
person('yuriki',21,job = 'student')
#person('shit',32,city = 'tokyo',job = 'singer',worksite = 'osaka') #报错

输出:

name =  brown age =  14 other information =  {}
name =  dick age =  12 other information =  {'city': 'New York'}
name =  Mary age =  14 other information =  {'gender': 'female'}
name =  Jerry age =  16 other information =  {'city': 'sydney', 'country': 'australia'}
你好
name =  Frank age =  24 other information =  {'job': 'actor', 'zipcode': 123456}
name =  Linawei age =  18 other information =  {'worksite': 'hospital', 'city': 'beijing'}
shit 32 tokyo singer
yuriki 21 osaka student

tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple:
字符串’xxx’也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:

如何判断一个对象是可迭代对象呢?方法是通过collections.abc模块的Iterable类型判断:

>>> from collections.abc import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
>>> isinstance([1,2,3], Iterable) # list是否可迭代
True
>>> isinstance(123, Iterable) # 整数是否可迭代
False

最后一个小问题,如果要对list实现类似Java那样的下标循环怎么办?Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:

同时引用了两个变量,在Python里是很常见的,比如下面的代码:

>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
...     print(x, y)
...
1 1
2 4
3 9

引入方法:

import math
j = math.cos(math.pi / 3)
print(j)

列表生成式:

if … else
使用列表生成式的时候,有些童鞋经常搞不清楚if…else的用法。

例如,以下代码正常输出偶数:

>>> [x for x in range(1, 11) if x % 2 == 0]
[2, 4, 6, 8, 10]

但是,我们不能在最后的if加上else:

>>> [x for x in range(1, 11) if x % 2 == 0 else 0]
  File "<stdin>", line 1
    [x for x in range(1, 11) if x % 2 == 0 else 0]

SyntaxError: invalid syntax

这是因为跟在for后面的if是一个筛选条件,不能带else,否则如何筛选?

另一些童鞋发现把if写在for前面必须加else,否则报错:

>>> [x if x % 2 == 0 for x in range(1, 11)]
  File "<stdin>", line 1
    [x if x % 2 == 0 for x in range(1, 11)]
                   ^
SyntaxError: invalid syntax

这是因为for前面的部分是一个表达式,它必须根据x计算出一个结果。因此,考察表达式:x if x % 2 == 0,它无法根据x计算出结果,因为缺少else,必须加上else:

>>> [x if x % 2 == 0 else -x for x in range(1, 11)]
[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]

上述for前面的表达式x if x % 2 == 0 else -x才能根据x计算出确定的结果。

可见,在一个列表生成式中,for前面的if … else是表达式,而for后面的if是过滤条件,不能带else。

生成器:

g = (x*x for x in range(10))
print(g) #generator的地址
print(next(g)) #generator的下一个元素
#generator的优点,节省空间
def fib(max):
    n , a , b = 0 , 0 , 1
    while n < max:
        yield b #加了这个关键字后fib函数就变成了generator函数了
        a , b = b , a+b
        n = n + 1
    return 'done'
f = fib(6)
print(f) #发现输出f后返回的是generator的地址

# 这里,最难理解的就是generator函数和普通函数的执行
# 流程不一样。普通函数是顺序执行,遇到return语句
# 或者最后一行函数语句就返回。而变成generator的函
# 数,在每次调用next()的时候执行,遇到yield语句返
# 回,再次执行时从上次返回的yield语句处继续执行。

def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)
o = odd()
print(next(o))
next(o)
d = next(o)
print(d)
#next(o) #第四次调用generator,直接报错,因为函数里没有更多的yield等返回语句了

# 请务必注意:调用generator函数会创建一个generator对象
# ,多次调用generator函数会创建多个相互独立的generator。

from collections.abc import Iterator

print(isinstance((x for x in range(10)), Iterator))
#可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator,可以发现生成器就是迭代器

输出:

<generator object <genexpr> at 0x000002466A019A10>
0
<generator object fib at 0x000002466A019A80>
step 1
1
step 2
step 3
5
True

用一般方法和生成器解决杨辉三角形问题:

def ttriangle(x):
    a = [1,]
    print(a)
    if(x < 2) : return
    for n in range(1,x):
        b = []
        for m in range(0,n+1):
            if(m == 0):
                b.append(int(a[0]))
            elif(m == n):
                b.append(int(a[n-1]))
            else:
                b.append(int(a[m-1]) + int(a[m]))
        print(b)
        a = b
    return

def triangle2():
    yield [1]
    l = [1,1]
    yield l
    while True:
        l = [1] + [l[x-1]+l[x] for x in range(len(l)) if(x != 0)] + [1]
        yield l

e = triangle2()
print(next(e))
print(next(e))
print(next(e))
print(next(e))

输出:

[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]

迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如list、tuple、dict、set、str等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

可以使用isinstance()判断一个对象是否是Iterable对象:
为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。