#08-09.语句、表达式、流程控制

[TOC]

零、代码风格问题

###0.0 缩进
1)python使用强制缩进的方式,使用4个空格或者tab缩进,建议使用4个空格。

###0.1PEP-8规范
1)空格和table不能混用,平时使用4个空格键
2)建议代码的长度不要超过79字符,现在可以直接换行,不需要使用续行符号\
3) 函数和函数之间空2行
4)pycharm中的一键PEP8:Ctrl+Alt+L

##一、语句
###1.1什么是语句?

语句是实现了某一种行为的,以号结尾,当然有些复合语句是以右花括号结尾。python没有这个要求
表达式是对某一个或者多个变量进行了某种操作,它的整体具有一个值,它不能独立存在,必须存在于某个语句中。

###1.2 赋值语句
####1.2.1使用等号赋值

name = 'Jerry'

####1.2.2使用元组进行赋值
#####1.2.2.1多个变量同时赋值,变量和值数量一致

a , b = 11,22
print(a,b,sep='|')

结果:11|22
以上就是省略了()的元组的赋值,实际等价于(a , b) = (11,22)

#####1.2.2.2任意多的变量也可以进行赋值:
不只局限于2个变量的赋值,任意多的变量也可以和相同数量的值进行赋值

# 可以将和字符串一样多的元素进行赋值
a, b, c, d, e, f = 'Hytera'
print(a, b, c, d, e, f, sep='|', end=' ')
>>>H|y|t|e|r|a 

####1.2.3多个变量同时赋值,变量和值数量不一致
如果变量的个数和值的个数不一致,则会报错

a, b, c = 1,2
print(a,b,c)

>>>Traceback (most recent call last):
  File "D:/str_2_unicode/str_2_unicode.py", line 1, in <module>
    a, b, c = 1,2
ValueError: not enough values to unpack (expected 3, got 2)

#####1.2.3.1通过切片的方法
如果涉及到字符串的赋值,本来就想将不同数量的值赋给变量,可以用字符串的切片的方法

str1 = 'HelloKitty'
a, b, c = str1[:1],str1[1:8],str1[8:]
print(a,b,c)

>>>H elloKit ty

#####1.2.3.2通过*的方法,扩展序列的解包赋值
1、python中的*表示是多个参数的意思,发送非键值对的可变数量参数给函数,表示不知道究竟会传递多个少个参数;
2、但是注意的是带*的变量会放到一个序列里面去,下面的例子将多个数量的参数放到tuple中。

def func(*args):
    print(f'Type of args is:{type(args)}')
    print(args)

l = [1,3,5,7,9]
func(l)
func(2,3,4,5)
func('name','age','position','degree')

输出:


Type of args is:<class 'tuple'>
([1, 3, 5, 7, 9],)
Type of args is:<class 'tuple'>
(2, 3, 4, 5)
Type of args is:<class 'tuple'>
('name', 'age', 'position', 'degree')

如果传递的是一个键值对,也会将键值对放到一个tuple中

def func(*args):
    print(f'Type of args is:{type(args)}')
    print(args)

l = [1,3,5,7,9]
func(l)
func(2,3,4,5)
func('name','age','position','degree')

d ={1:'apple',2:'orange',3:'kiwi',4:'orange'}
func(d)

3、还有一种**kwargs表示传递的是多个键值对

def func2(**kwargs):
    print(f'Type is:{type(kwargs)}')
    print(kwargs)
func2(a=1,b=2,c=3)
输出:
Type is:<class 'dict'>
{'a': 1, 'b': 2, 'c': 3}

另外一个例子,如果传递的是一个键值对,参数要用**d的形式,否则会报错。

def func2(**kwargs):
    print(f'Type is:{type(kwargs)}')
    print(kwargs)


d = {'1': 'apple', '2': 'orange', '3': 'kiwi', '4': 'orange'}
func2(**d)
func2(d)
运行结果:
Type is:<class 'dict'>
{'1': 'apple', '2': 'orange', '3': 'kiwi', '4': 'orange'}
Traceback (most recent call last):
  File "D:\SynologyDrive\python\语句和控制流程\test.py", line 8, in <module>
    func2(d)
TypeError: func2() takes 0 positional arguments but 1 was given

######1.2.3.2.1最后一个值为多个值

a, b, *c = 'Hytera'
print(a, b, c)


# 注意这里的的`c`是一个list的序列
>>>H y ['t', 'e', 'r', 'a']

######1.2.3.2.2中间的变量为多个值
同样的,也会将前后的单个值赋值给变量,中间的部分作为序列赋值给中间的变量

a, *b, c = 'Hytera'
print(a, b, c)

# 注意中间b的值
H ['y', 't', 'e', 'r'] a

#####1.2.3.3值的个数比变量的个数要少
一个表达式里面只能有一个*,如果存在多个*也会报错
值的个数比变量的要少,同样也会报错的。

####1.2.4交换两个值
值的交换,实际就是使用元组进行操作的

a, b = b, a

####1.2.5多目标赋值
#####1.2.5.1将一个值赋值给多个变量
可以将几个变量指向同一个值
Alt text

>>> a = b = c = 20
>>> a,b,c
(20, 20, 20)

>>> id(a),id(b),id(c)
(2785567268080, 2785567268080, 2785567268080)

需要注意的是,这里变量都是引用的同一个地址,如果改变任意一个,都会导致其他的变量改变。
可以通过:单独赋值,序列赋值来实现互不影响的赋值。
单独赋值

a = []
b = []

序列赋值

>>> a,b = [],[]
>>> a
[]
>>> b
[]
>>> b.append('book')
>>> a,b
([], ['book'])
1.2.5.2字符串的 a is b ? 多少个字符是false,多少个是false?
 >>> a = 'Jerry'
>>> b='Jerry'
>>> a is b
True
>>> a = 'HyteraCommunication'
>>> b = 'HyteraCommunication'
>>> a is b
True

不同的情况:https://segmentfault.com/q/1010000002666462

这里脚本和交互式提示符处理是不同的。

简单来说就是:在交互式环境下,Python只会对包含Python identifiers(下划线、数字、字母)的字符串进行intern。空格不属于Python identifiers。所以,id(c) != id(d)。
感兴趣的可以去查看一下Python源码里的stringobject.h文件,注释上有这么一段:

This is generally restricted to strings that "look like"
Python identifiers, although the intern() builtin can be used to force
interning of any string.

当然,Python的内部机制不会这么简单的,会存在特殊处理的情况。比如执行>>> a = " ",>>> b = " ",>>> a is b得到的结果是True。存在这个矛盾的情况是因为对于0或1个字符的字符串,Python是进行了intern处理的。

可见,对于任意字符串Python都是可以进行intern处理的,只不过对于问题中的情况,Python在实现时选择了不处理而已,所以说,这是一个实现的问题,不是语言特性。

另外,你可以将代码写到脚本中,会发现得到的都是True。

并且之前讲过的小整数的内存池,在REPL和脚本下都是不同的表现

a = 30000000
b = 30000000
print(a is b)
>>>True

####1.2.6参数化赋值
使用参数化赋值,效率会更高。注意顺序,+和*不存在这个问题,除法和减法有顺序,是a在前面。
+= a+=b等价于a=a+b
-= a-=b等价于a=a-b
*=a*=b等价于a=a*b
/=a/=b等价于a=a/b
%= a%=b等价于'a = a%b'
//= a//=b等价于a=a//b

# +=的操作
a = 1
b = 2
a += b
print("a={},b={},a+=b操作后,a={}".format(1, 2, a))

# -=的操作
a = 10
b = 23
a -= b
print("a={},b={},a-=b操作后,a={}".format(10, 23, a))

# *=的操作
a, b = 3, 6
a *= b
print("a={},b={},a*=b操作后,a={}".format(3, 6, a))

# /=的操作
a, b = 3, 10
a /= b
print("a={},b={},a /= b操作后,a={}".format(3, 10, a))

"C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
a=1,b=2,a+=b操作后,a=3
a=10,b=23,a-=b操作后,a=-13
a=3,b=6,a*=b操作后,a=18
a=3,b=10,a /= b操作后,a=0.3

列表的参数化赋值、append()和extend()的回顾
append()添加的元素为一个,extend为扩展到序列里面。

##二、表达式
###2.1函数调用
可以调用全局的函数:len() input() list() dict() str()....

###2.2方法的调用
方法是依附于对象的操作,函数不用。
###2.3字面值

s ='HelloKitty'
print(s)

###2.4print()语句直接打印到文件
可以不通用事先创建文件,直接打印到文件内容

print('HelloKitty','HarryPorter',sep='|',end=' ',file=open(r'd:\test.txt','w'))

img
##三、流程控制
###3.1 if语句
####3.1.1最简单的if语句
判断一个结果 score 的值,if...else...

score = 55
if score >= 60:
    print('Pass')
else:
    print('Not pass')

if elif语句实现多重分支

score = 95

if score >= 90:
    print('优秀')
elif score >= 60:
    print('及格')
else:
    print('不及格')

####3.1.2使用dict变通实现switch的语句

def print_excellent():
    print('优秀')
def print_good():
    print('良好')
def print_pass():
    print('及格')
def print_not_pass():
    print('不及格')
def print_unknown():
    print('输入有误,成绩未知')

# 输入一个key,通过dict来获取其值
# dict.get()方法如果查找不到,会返回一个default内容
# 这里需要注意的是:定义的字典的值,是函数名称的引用,而不是字符串
# 另外使用dict()函数,key是不需要加上''的
d = dict(A=print_excellent, B=print_good, C=print_pass, D=print_not_pass)

while True:
    s = input()
    d.get(s, print_unknown)()

以上实现了一个switch的方法应用,通过输入不同值,得到不同的结果。
####3.1.3三元表达式
三元表达式,用简短的语句实现结果的判断和赋值。
基本语法是:返回值 = 成立值 if 条件 不成立值,如果if条件成立,就取值成立,否则就去不成立值。

frq = 380

# 以下是三元表达式
bandwidth = 4 if frq > 400 else '其他频段'
print(bandwidth)
>>>其他频段

###3.2 while语句
####3.2.1while的一般格式:条件测试
while语句是要设置条件,并且后面,要改变条件让其不满足后退出while循环。

while 条件:
.... 改变条件

x = 10

while x:
    print(x, end=' ')
    x -= 1
>>>10 9 8 7 6 5 4 3 2 1 

#####3.2.1.1 死循环
死循环都是设置了循环条件一直为真,在REPL环境下可以通过Ctr+C来结束

while True:
    print('Hello')
    
Traceback (most recent call last):
  File "<input>", line 2, in <module>
KeyboardInterrupt

#####3.2.1.2 循环的基本流程
while需要先指定一个条件,后面再改变这个条件。
例如逐个输出一个字符串的值,想用如下的语法是行不通*的,因为while判断s是否在str里面,而不是遍历。

str1 = 'Hellokitty'

while s in str1:
    print(s, end=' ')

但是用for是可以实现的,隐约感到for有遍历迭代数据的功能,while没有😺

str1 = 'Hellokitty'

for s in str1:
    print(s, end=' ')

so...如何用while来实现,遍历字符串的功能呢?
这例子更看重的是具体的方法,其中核心部分就是每次都输出第一个,然后缩短这个字符串

str1 = 'Hellokitty'

while str1:
# 每次都输出第一个元素
# 将字符串缩短一个后赋值给str1
    print(str1[0],end=' ')
    str1 = str1[1:]
else:
    print('遍历完毕!')

while条件判断为假和真的有那些?
False -- 假
None -- 假
0 -- 假
list/字符换 为空 -- 假

True -- 真
1 -- 真
负数 -- 真
整数 -- 真

#####3.2.1.3 break continue pass else

3.2.1.3.1break实现立即直接跳出循环体的功能,后面的循环都不再执行

img

x = 1

while True:
    print(x, end=' ')
    if x == 10:
        break
    x += 1

"C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
1 2 3 4 5 6 7 8 9 10 
3.2.1.3.2函数中的return语句同样也会立即跳出循环

如下的例子中,x会增加,当x等于10的时候就返回值,此时循环就停止了

def fun(x):
    while True:
        print(x)
        if x == 10:
            return x
        x += 1
print('函数返回会打断循环:', fun(1))
"C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
1 2 3 4 5 6 7 8 9 10 函数返回会打断循环: 10 
Process finished with exit code 0

输入一个名字,并打招呼,如果输入q字符则break循环

while True:
    name = input('Enter name:')
    if name.lower() == 'q':
        break
    print('Hello {}'.format(name))
"C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
Enter name:Eric
Hello Eric
Enter name:Q

Process finished with exit code 0
3.2.1.3.3continue语句可以结束当前循环,进行下一个循环
x = 10
while x > 0:
    x -= 1
    if x % 2 != 0:
        continue
    print(x, end=' ')
   "C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
8 6 4 2 0 
Process finished with exit code 0

while...else... 查找一个值的函数,记得找到后要break

x = 10
listA = [1,2,3,45]

while x in listA:
    print('找到了')
    break
else:
    print('没有找到')

###3.3 for循环语句
for x in 目标序列:
for遍历list

a = list(range(1, 10))
for i in a:
    print(i,end=' ')
"C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
1 2 3 4 5 6 7 8 9 
Process finished with exit code 0

for遍历str

str1 = 'Hellokitty'
for s in str1:
    print(s, end=' ')
    
"C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
H e l l o k i t t y 
Process finished with exit code 0

for遍历tuple

tup = tuple('HelloKitty')
for t in tup:
    print(t,end=' ')

for遍历dict

book = dict(title='Python', author='Tony', price=90.00)
for key in book.keys():
    print(key)
for value in book.values():
    print(value)
for key, value in book.items():
    print(key, value)

###3.3.1一些例子
找出两个字符串中的交集的部分(for 推导)

str1 = 'Tonight is beautiful'
str2 = 'sleeping beauty'
common_content = [s for s in str2 if s in str1]
print(common_content)
# 同样可以简单的使用集合来求得两个集合的交集
s1 = set(str1)
s2 = set(str2)
common_list = s1 & s2
print(common_list)
"C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
['s', 'l', 'e', 'e', 'i', 'n', 'g', ' ', 'b', 'e', 'a', 'u', 't']
{'e', 's', 'b', 'l', 'u', 'n', 'i', 't', 'g', ' ', 'a'}

###3.4 range()函数
range()函数可以方便生成指定的
###3.4.1 range的取值区间
range(a,b),实际的取值是[a,b),其中末尾是开区间。还有很多比如说通过index访问列表的元素,也是开区间。
####3.4.2 range()返回值是一个生成器对象
生成器并不是返回所有的值,而是你在使用的时候生成的

"C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
<class 'range'>
print r is: range(1, 11)

####3.4.3 range的步长参数
可以通过range(a,b,step)的方式来指定range的步长,其中的参数如下:
img

r = range(1, 11, 2)
for i in r:
    print(i, end=' ')

可以可以快速来生成奇数或者偶数,或者指定步进值的序列。
需要注意的一点是,后面的步进值是一个整数,不能为float类型。
实际的例子,如果要打印频率,使用如下方法不行

r = range(380, 430, 0.25)
for i in r:
    print(i, end=' ')

可以变通,将step设置为整数

r = range(380*1000, 430*1000, 25)
for i in r:
    print('{:.4f}'.format(i/1000), end=' ')

380.0000 380.0250 380.0500 380.0750 380.1000 380.1250 380 ...

###3.5可迭代对象的枚举类型:enumerate
读音:英 [ɪ'njuːməreɪt] 意思:枚举
可迭代对象可以通过 enumerate(迭代对象)的方式来输出(索引,值)
####3.5.1使用enumerate输出list的索引和值,tuple的方式

l = list(range(1, 11))
for i in enumerate(l):
    print(i)
(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
(5, 6)
(6, 7)
(7, 8)
(8, 9)
(9, 10)

####3.5.2使用enumerate输出可迭代对象的索引和值,输出值的方式

l = list(range(1, 11))
for i,v in enumerate(l):
    print(i,v)
"C:\Program Files\Python35\python.exe" D:/str_2_unicode/str_2_unicode.py
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10

####3.5.3使用enumerate的一个例子

The number 89 is the first integer with more than one digit that fulfills the property partially introduced in the title of this kata. What's the use of saying "Eureka"? Because this sum gives the same number.
In effect: 89 = 81 + 92
The next number in having this property is 135.
See this property again: 135 = 11 + 32 + 5^3
We need a function to collect these numbers, that may receive two integers a, b that defines the range [a, b] (inclusive) and outputs a list of the sorted numbers in the range that fulfills the property described above.
Let's see some cases:
sum_dig_pow(1, 10) == [1, 2, 3, 4, 5, 6, 7, 8, 9]
sum_dig_pow(1, 100) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 89]
If there are no numbers of this kind in the range [a, b] the function should output an empty list.
sum_dig_pow(90, 100) == []
以及使用enumerate的解决方法:

def filter_func(a):
    return sum(int(d) ** (i+1) for i, d in enumerate(str(a))) == a

def sum_dig_pow(a, b):
    return filter(filter_func, range(a, b+1))

关于filter()函数:http://www.runoob.com/python/python-func-filter.html

def dig_pow(n):
    return sum(int(x)**y for y,x in enumerate(str(n), 1))
def sum_dig_pow(a, b): 
    return [x for x in range(a,b + 1) if x == dig_pow(x)]

####3.5.4 filter(function, iterable)

用 iterable 中函数 function 返回真的那些元素,构建一个新的迭代器。iterable 可以是一个序列,一个支持迭代的容器,或一个迭代器。如果 function 是 None ,则会假设它是一个身份函数,即 iterable 中所有返回假的元素会被移除。

请注意, filter(function, iterable) 相当于一个生成器表达式,当 function 不是 None 的时候为 (item for item in iterable if function(item));function 是 None 的时候为 (item for item in iterable if item) 。

请参阅 itertools.filterfalse() 了解,只有 function 返回 false 时才选取 iterable 中元素的补充函数。

l = ['Lucy', 'Lily','JimGreen','Han Meimei','Poly']

def func(s):
    if 'e' in s:
        return True

res = filter(func,l)
print(type(res))
res = list(res)
for r in res:
    print(r)
    
输出:
<class 'filter'>
JimGreen
Han Meimei

这里针对python2和python3有些不同,python2中返回的是过滤后的列表,python3中返回的是filter类

posted on 2022-07-27 17:14  飞飞fly  阅读(67)  评论(0编辑  收藏  举报