本日志中的学习教材来自于https://github.com/jackfrued/Python-100-Days
如果大家想进一步学习,最好看看这个教材,超级棒
一.简单结构
1.分支结构
python对与缩进好像有着执念(?
看哈
if
if
else
elif
else
这样的才能一一对应,而且接下来的缩进格式必须保持相同,否则,就,不是,同一个段落了(离谱)
2.循环结构
2.1 明确range的概念
1)range(1,101)->[1,100)
2)range(1,101,2)->产生1-100的奇数,2是步长
3)range(100,0,-2)->产生100-1的偶数,-2是步长
2.2 for循环的介绍
1)标准写法:
for x in range(1, 101):
if x % 2 == 0:
sum += x
python 的for很简练,变量定义的时候自动归为range下限,若没有range下限,就默认为0
(想试试的话,把range里面那个1删掉就好,然后print x就可以看到了)
2.3while循环
while和for循环互换挺方便的其实,不过while更多的用于不知道循环次数的情况
这玩意挺有趣的
这里直接插书里的代码了
"""
猜数字游戏
Version: 0.1
Author: 骆昊
"""
import random
answer = random.randint(1, 100)
counter = 0
while True:
counter += 1
number = int(input('请输入: '))
if number < answer:
print('大一点')
elif number > answer:
print('小一点')
else:
print('恭喜你猜对了!')
break
print('你总共猜了%d次' % counter)
if counter > 7:
print('你的智商余额明显不足')
这个while甚至没有终止条件,只有猜对了才跑的出来(智商余额真的不足的话咋办[狗头])
二、简单函数介绍
1.函数作用
当代码重复率过高的时候,不妨将它归纳到函数中
2.函数应该如何定义呢?
这里还是引用书中的代码
"""
输入M和N计算C(M,N)
Version: 0.1
Author: 骆昊
"""
def fac(num):
"""求阶乘"""
result = 1
for n in range(1, num + 1):
result *= n
return result
def+函数名,然后开始操作即可。它有个小坑
注意那个return的位置
3.函数细碎知识点
3.1函数参数
python中函数不需要重载,它自己就可以去找最适合它的函数,这还不算离谱,更离谱的是,当你对参数一无所知的时候,你甚至可以搞一个可变参数出来(大离谱)
# 在参数名前面的*表示args是一个可变参数
def add(*args):
total = 0
for val in args:
total += val
return total
# 在调用add函数时可以传入0个或多个参数
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
print(add(1, 3, 5, 7, 9))
还是引用的书里的代码
简直太离谱了好嘛,python就像是一个长大的孩子,懂得自己做饭吃。c艹:“你再骂!”
3.2模块化的概念
就是,当你有一个相当大相当大的程序需要大家合作完成的时候,函数定义重名的情况。(心有灵犀一点通)
那应该如何解决呢?
python中每个文件就是一个模块,我们要做的就是import(引入)的时候,给他搞一个独特的名字,module1.py就叫他m1吧,然后就像c里面的命名空间那样,m1.foo()它就被成功独立的调用啦[还有很多方法,不过我觉得这个是最成熟的做法(窃以为)]
---------小tip--------
如果我们的模块里有可执行代码,那应该咋子办咯?我们并不希望导入的模块里输出一堆看不懂的幺蛾子对吧。同样,我们写出的模块也不希望被别人骂成幺蛾子,所以我们写的时候就要注意:把执行代码放入下面的条件里(这个条件可以重复使用的)
# __name__是Python中一个隐含的变量它代表了模块的名字
# 只有被Python解释器直接执行的模块的名字才是__main__
if __name__ == '__main__':
print('call foo()')
foo()
print('call bar()')
bar()
4.变量的作用域
这里老师说的话实在太精炼,精彩的,我就不徒增笑柄了[不是因为懒]
def foo():
b = 'hello'
# Python中可以在函数内部再定义函数
def bar():
c = True
print(a)
print(b)
print(c)
bar()
# print(c) # NameError: name 'c' is not defined
if __name__ == '__main__':
a = 100
# print(b) # NameError: name 'b' is not defined
foo()
“上面的代码能够顺利的执行并且打印出100、hello和True,但我们注意到了,在bar
函数的内部并没有定义a
和b
两个变量,那么a
和b
是从哪里来的。我们在上面代码的if
分支中定义了一个变量a
,这是一个全局变量(global variable),属于全局作用域,因为它没有定义在任何一个函数中。在上面的foo
函数中我们定义了变量b
,这是一个定义在函数中的局部变量(local variable),属于局部作用域,在foo
函数的外部并不能访问到它;但对于foo
函数内部的bar
函数来说,变量b
属于嵌套作用域,在bar
函数中我们是可以访问到它的。bar
函数中的变量c
属于局部作用域,在bar
函数之外是无法访问的。事实上,Python查找一个变量时会按照“局部作用域”、“嵌套作用域”、“全局作用域”和“内置作用域”的顺序进行搜索,前三者我们在上面的代码中已经看到了,所谓的“内置作用域”就是Python内置的那些标识符,我们之前用过的input
、print
、int
等都属于内置作用域。”
不过学习还是要将知识转换为自己的
我个人理解呢,他是说 全局>函数内定义>函数中的函数定义,并且小的里面不可以修改大的,但可以访问大的。大的里面不可以修改小的,也访问不到小的
但有没有办法让小的修改了大的呢?
有!
在函数中加一句global 变量名,如果有全局,就可以改全局,没有就定义了一个
在函数中的函数里访问函数变量,需要加一个nonlocal
不过全局变量是一个很糟糕的习惯,我之前在用一个小软件做游戏的时候就体会到了,谁都可以访问,都可以改变,等一圈调用下来,你已不再是你,我也不再想调。还是少用的好!
三、常用 的数据结构归纳
我是因为这块知识点太杂,学起来实在太困难了,所以才会想着开博客总结的(xx)
3.1 字符串
没啥好说的,和c++里的string感觉用着没啥区别
这里有一个小技巧需要插播
print(s1,end='')可以免去print后的换行
r’\nhello‘可以让\不表示转义
还是插入代码
s1 = 'hello ' * 3
print(s1) # hello hello hello
s2 = 'world'
s1 += s2
print(s1) # hello hello hello world
print('ll' in s1) # True
print('good' in s1) # False
str2 = 'abc123456'
# 从字符串中取出指定位置的字符(下标运算)
print(str2[2]) # c
# 字符串切片(从指定的开始索引到指定的结束索引)
print(str2[2:5]) # c12
print(str2[2:]) # c123456
print(str2[2::2]) # c246
print(str2[::2]) # ac246
print(str2[::-1]) # 654321cba
print(str2[-3:-1]) # 45
大家可以看一下,重复操作,查验是否包含,取出指定位置的字符,切片都在这里了
str1 = 'hello, world!'
# 通过内置函数len计算字符串的长度
print(len(str1)) # 13
# 获得字符串首字母大写的拷贝
print(str1.capitalize()) # Hello, world!
# 获得字符串每个单词首字母大写的拷贝
print(str1.title()) # Hello, World!
# 获得字符串变大写后的拷贝
print(str1.upper()) # HELLO, WORLD!
# 从字符串中查找子串所在位置
print(str1.find('or')) # 8
print(str1.find('shit')) # -1
# 与find类似但找不到子串时会引发异常
# print(str1.index('or'))
# print(str1.index('shit'))
# 检查字符串是否以指定的字符串开头
print(str1.startswith('He')) # False
print(str1.startswith('hel')) # True
# 检查字符串是否以指定的字符串结尾
print(str1.endswith('!')) # True
# 将字符串以指定的宽度居中并在两侧填充指定的字符
print(str1.center(50, '*'))
# 将字符串以指定的宽度靠右放置左侧填充指定的字符
print(str1.rjust(50, ' '))
str2 = 'abc123456'
# 检查字符串是否由数字构成
print(str2.isdigit()) # False
# 检查字符串是否以字母构成
print(str2.isalpha()) # False
# 检查字符串是否以数字和字母构成
print(str2.isalnum()) # True
str3 = ' jackfrued@126.com '
print(str3)
# 获得字符串修剪左右两侧空格之后的拷贝
print(str3.strip())
同样,一系列函数也在这里了,有手就行(我手呢...)
3.2列表
列表咋子讲,和字符串 的应用也有点差不多噻。还是直接上书吧
list1 = [1, 3, 5, 7, 100]
print(list1) # [1, 3, 5, 7, 100]
# 乘号表示列表元素的重复
list2 = ['hello'] * 3
print(list2) # ['hello', 'hello', 'hello']
# 计算列表长度(元素个数)
print(len(list1)) # 5
# 下标(索引)运算
print(list1[0]) # 1
print(list1[4]) # 100
# print(list1[5]) # IndexError: list index out of range
print(list1[-1]) # 100
print(list1[-3]) # 5
list1[2] = 300
print(list1) # [1, 3, 300, 7, 100]
# 通过循环用下标遍历列表元素
for index in range(len(list1)):
print(list1[index])
# 通过for循环遍历列表元素
for elem in list1:
print(elem)
# 通过enumerate函数处理列表之后再遍历可以同时获得元素索引和值
for index, elem in enumerate(list1):
print(index, elem)
这里需要注意的是
print(list1[-1]) # 100 print(list1[-3]) # 5
它这个-1,-3注意它指的是哪个数。以及-5会不会out of range
还有后面的两种遍历方式,一种是下标访问的方法,另一种是直接从list里面取
list1 = [1, 3, 5, 7, 100]
# 添加元素
list1.append(200)
list1.insert(1, 400)
# 合并两个列表
# list1.extend([1000, 2000])
list1 += [1000, 2000]
print(list1) # [1, 400, 3, 5, 7, 100, 200, 1000, 2000]
print(len(list1)) # 9
# 先通过成员运算判断元素是否在列表中,如果存在就删除该元素
if 3 in list1:
list1.remove(3)
if 1234 in list1:
list1.remove(1234)
print(list1) # [1, 400, 5, 7, 100, 200, 1000, 2000]
# 从指定的位置删除元素
list1.pop(0)
list1.pop(len(list1) - 1)
print(list1) # [400, 5, 7, 100, 200, 1000]
# 清空列表元素
list1.clear()
print(list1) # []
这个里面 pop那里有点东西,pop指定的位置
3.3 生成式和生成器
1)可以用生成式的语法来创建列表
f = [x for x in range(1, 10)]
2)生成器对象
1.可以获得数据,但不占用额外的空间存储数据
2.每次需要数据就通过内部的运算得到数据
3)可以用yield
将普通函数改造成生成器函数(斐波那契数列)
4.元组
就是一个固定的不可增加删除的数组
具体 的优点可以看我这个总结,敲字手累了QAQ
5.集合
啥也不说了,跟高中学的集合一样样的,不能有重复元素什么的
注意的一点就是 差集,对称差的区别
6.字典
给一个小玩意赋值,然后根据值去索引,有点像c++里的map。