Python语法概念基础详解
目录
- Python之禅:
- Python基础:
- 1. 进制转换:
- 2. 数据类型:
- 3. 单双引号转义字符的使用:
- 4.单双三引号的转义换行:
- 5.字符串的运算:
- 6.组的概念与含义:
- 7.集合:
- 8.系统关键字与引用的可变性和值的不可变性:
- 9.逻辑运算符:
- 10.分支,条件,循环,枚举,包,模块,函数:
- 11.面向对象基本知识:
- 12.运算符优先级问题:
- 13.代码自动调节工具pep8:
- 14.python库的安装:
- 15.解决pip超时问题:
- 总结
- (本章节主要是一些python的基础语法,具体内容不够详细,以pycharm下调试产生的部分代码为主)
- (python语法的详细内容请参考官方教程或者经典书籍)
- (在架构方面来看,或者程序的设计思路来看,语法并不是一个很重要的东西,语法部分过于细节,而且很多很繁杂;但是对于程序或者功能的实现来说,语法概念却是基础,是程序的血肉,只有熟练掌握语法的基础知识,才能更好更快速的写好程序)
Python之禅:
''' The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! •优美胜于丑陋(Python 以编写优美的代码为目标) •明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似) •简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现) •复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁) •扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套) •间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题) •可读性很重要(优美的代码是可读的) •即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上) •不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码) •当存在多种可能,不要尝试去猜测 •而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法) •虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido ) •做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量) •如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准) •命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召) '''
Python基础:
1. 进制转换:
>>> bin(1) '0b1' >>> bin(9) '0b1001' >>> oct(90) '0o132' >>> bin(9) '0b1001' >>> bin(1) '0b1' >>> oct(10) '0o12' >>> oct(9) '0o11' >>> hex(14) '0xe' >>> hex(15) '0xf' >>> 10 10 >>> 11 11 >>> oct(0b10) '0o2' >>> oct(0b111) '0o7' >>> hex(100) '0x64' >>> hex(0b1111) '0xf' >>> hex(0o77) '0x3f'
2. 数据类型:
Python基本数据类型: 数字:整型int,浮点型float,bool型,复数complex 组分为序列,集合,字典 序列(有序(此处有序是指输入后顺序不改变,即不具备自动排序功能),可下标索引,切片操作):字符串str,列表list,元组tuple 集合set:无序(此处的无序是指输入后set内部进行自己排序,导致序列可能与之前的不同),没有索引,不能切片 字典dict:({key,value}是其基本概念与形式) >>> type(1) <class 'int'> >>> type(1.1) <class 'float'> >>> type((1,1)) <class 'tuple'> >>> type((1,2)) <class 'tuple'> >>> type((1,1,1,)) <class 'tuple'> >>> type([1,1,1,1]) <class 'list'> >>> type(None) <class 'NoneType'> >>> type(36j) <class 'complex'> >>> type('a') <class 'str'> >>> type("a") <class 'str'> >>> type('''a''') <class 'str'> >>> type(True) <class 'bool'> >>> type(False) <class 'bool'> >>> type(['hello', 'world', 90, True, False]) <class 'list'> >>> type({}) <class 'dict'> 空集合表示方法: >>> type(set()) <class 'set'> >>> type({1,2,3}) <class 'set'> >>> type({1,'2',3.3,True}) <class 'set'> 需要注意的是True与False的区别(集合是自动排序的): >>> {1,'2',3.3,True} {'2', 1, 3.3} >>> {1,'2',3.3,False} {'2', 1, 3.3, False}
3. 单双引号转义字符的使用:
转义字符的使用: 当使用IDLE直接输出时: 例: '"k"' 输出:'"k"' "'k'" 输出:"'k'" 转义字符的使用: 单一转义均可转(转双引号显示‘',转单引号显示“”): >>> 'lets\'go' "lets'go" >>> 'lets\'go''lets\'go' "lets'golets'go" >>> 'lets\"go''lets\"go' 'lets"golets"go' >>> "lets\"go""lets\"go" 'lets"golets"go' >>> "lets\'golets\'go" "lets'golets'go" >>> 'lets\"go'"lets\"go" 'lets"golets"go' >>> "lets\'go"'lets\'go' "lets'golets'go" 转义混合只转双(由于只转双引号,因此全显示‘'): >>> "lets\"go""lets\'go" 'lets"golets\'go' >>> "lets\'go""lets\"go" 'lets\'golets"go' >>> 'lets\'go''lets\"go' 'lets\'golets"go' >>> 'lets\"go''lets\'go' 'lets"golets\'go' >>> "lets\"go"'lets\'go' 'lets"golets\'go' >>> 'lets\'go'"lets\"go" 'lets\'golets"go' >>> "lets\'go"'lets\"go' 'lets\'golets"go' >>> 'lets\"go'"lets'go" 'lets"golets\'go' print函数直接转: >>> print('lets\"go''lets\'go') lets"golets'go >>> print('let\'sgolet\'sgo') let'sgolet'sgo
4.单双三引号的转义换行:
引入三引号便于在换行时可继续输入: 单双三引号换行方式: 正常不换行: >>> 'helloworld helloword' 'helloworld helloword' 三引号(单引号形式)换行: >>> '''helloword ... ''' 'helloword\n' >>> ''' ... hello world ... helloworld ... ''' '\nhello world\nhelloworld\n' 三引号(双引号形式)换行(与单引号形式的三引号没有区别): >>> """hello world ... hello world ... ''' ... """ "hello world\nhello world\n'''\n" >>> """ ... helloword ... 'kkk'' ... """ "\nhelloword\n'kkk''\n" >>> """ ... hello world ... "kkk"" ... """ '\nhello world\n"kkk""\n' 对于转义字符换行的使用(单双引号与三引号): >>> print("""\nhello\nhello""") hello hello >>> print("\nhello\nhello") hello hello print函数也是单双引号限制在同一行,三引号形式可多行 >>> print("hello File "<stdin>", line 1 print("hello ^ SyntaxError: EOL while scanning string literal >>> print('''hello ... hello''') hello hello 在后面加\可在下一行输入,但是是直接衔接,没有\n符号: >>> 'hello\ ... hello' 'hellohello' >>> print('hello File "<stdin>", line 1 print('hello ^ SyntaxError: EOL while scanning string literal >>> print('hello\ ... hello') hellohello
5.字符串的运算:
字符串的运算: 可加性: >>> 'hello'+'world' 'helloworld' 通过[]下标形式获取字符串的字符: >>> 'helloworld'[7] 'r' >>> 'hello'[0] 'h' 负数时从后面开始计数: >>> 'hello'[-1] 'o' >>> 'hello'[-2] 'l' >>> 'hello'[-4] 'e' 越界: >>> 'hello'[10] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: string index out of range >>> 'hello'[-10] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: string index out of range 字符串的截取(左闭右开区间,截取字符个数为右减左,但是要注意字符串是从0开始的)(格式:字符串后加[左区间:右区间]): >>> 'helloworld'[0:2] 'he' >>> 'helloworld'[1:5] 'ello' 我们截取到最后时可以数到最后一位截取,也可以超出规定位数进行截取: >>> 'hello'[0:5] 'hello' >>> 'hello'[0:20] 'hello' 负数表示概念:步长(从字符串末尾往回数几个字符)(负数在截取字符串中表示的含义与获取字符时相同,但是截取时是左闭右开区间,如果要截到最后一位(序号为-1),就要加一为0,但是实际操作并不是要写0,可看下面的例子): >>> 'helloworld'[0:-1] 'helloworl' >>> 'hellowprld'[0:0] '' >>> 'hello'[0:] 'hello' 由上面的这个例子可以推出: >>> 'hello'[:3] 'hel' 由前两个例子可以得到从头截取到尾的表示方法: >>> 'hello'[:] 'hello' 字符串不支持字符串间相乘,但是可以乘数字: >>> '1'*'1' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can't multiply sequence by non-int of type 'str' >>> "1"*8 '11111111'
6.组的概念与含义:
组(序列)的概念与含义: str(字符串),list(列表),tuple(元组)都可以看做序列: 每个元素都有一个序号: >>> (1,2,3)[1] 2 >>> [1,2,3][1] 2 >>> '123'[1] '2' bool类型在序列中的判断使用: in / not in: >>> 3 in [1,2] False >>> 3 in (1,2,3) True >>> 3in(1,2,3) True >>> 3 not in (1,2,3) False >>> 3 not in [1,2] True 注意字符串内判断要用‘' >>> '1' in '1234' True >>> 2 not in '134' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'in <string>' requires string as left operand, not int >>> '2' not in '134' True 首先要区分元组与列表: >>> 1,2 (1, 2) >>> (1,2) (1, 2) >>> type((1,2)) <class 'tuple'> >>> [1,2] [1, 2] >>> [[1],[2]] [[1], [2]] >>> [[1,2,3],[1,2,3,4,5]] [[1, 2, 3], [1, 2, 3, 4, 5]] >>> type([[1],[2]]) <class 'list'> [[1],[2]],[[1, 2, 3], [1, 2, 3, 4, 5]]又叫嵌套列表,实际就是二维数组 空元组与空列表(元组内表示单个元素时要加逗号,否则直接计算出来变为原来的数据类型): >>> ((1)) 1 >>> ('a') 'a' >>> ((1,)) (1,) >>> (1,) (1,) >>> () () >>> type((1,)) <class 'tuple'> >>> type(()) <class 'tuple'> >>> type([1]) <class 'list'> >>> type([]) <class 'list'> 列表内的数据类型可以不唯一: >>> ['hello','world',90] ['hello', 'world', 90] >>> type(['hello', 'world', 90]) <class 'list'> >>> ['hello', 'world', 90,True,False] ['hello', 'world', 90, True, False] >>> type(['hello', 'world', 90, True, False]) <class 'list'> 列表与字符串类似,也具有可加性: >>> [1,2]+[1] [1, 2, 1] 列表内元素的获取(类似于字符串相关截取操作): >>> [1,2,3,4][2] 3 >>> ['1','2','3'][2] '3' >>> ['1','2','3'][0:1] ['1'] >>> [1,'2',3][0:1] [1] >>> ['1',2,3][0:1] ['1'] 是字符串截取出字符串,是整型截取出整型,数据类型不会变。 需要注意的是,我们用冒号截取一段时,截取结果依然是列表,而我们不使用冒号获取单一元素时,截取结果的数据类型只是该元素的数据类型(比如我们截取“3”,那么截取结果的数据类型就是字符串,结果是‘3') 列表不支持列表间相乘,但是可以乘数字: >>> [1,2]*[1,2] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can't multiply sequence by non-int of type 'list' >>> [1,2]*3 [1, 2, 1, 2, 1, 2] 列表中一些函数的简单使用(len(),min(),max()等): >>> len([1,2,3]) 3 size是没有定义的: >>> size([1,2,3]) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'size' is not defined >>> max([1,2,3]) 3 未知量是无法比较的(并不是字符串的比较,未知量会出错): >>> max([a,b,c]) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a' is not defined >>> min(('a','b')) 'a' >>> max(['a','b']) 'b' 对字符串: >>> min('abcde') 'a' >>> max('aaa111ccc') 'c' >>> min('aaa111ccc') '1' >>> min('a b') ' ' 上面的例子实际是有输出的,是空格。 对于元组与列表的比较和对字符串的比较是不同的(字符串的比较是无论多少字符串只输出最大或最小的字符,而元组或列表是对每个元素的比较,元素可能就是字符串,那么就是对字符串的比较): >>> max('abbcc''bccaa') 'c' >>> max("abc""def") 'f' >>> max(["abc","cde"]) 'cde' >>> max(('abc','def')) 'def' ord()函数是直接输出字符(单个字母或符号,Python中无字符概念)所对应的ASCII码: 只能是单个字符: >>> ord('we') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: ord() expected a character, but string of length 2 found >>> ord('p') 112 空格所对应的ASCII码: >>> ord(' ') 32 单双引号均可(Python都表示字符串): >>> ord('0') 48 >>> ord("0") 48
7.集合:
集合(set)也是序列的一种: 集合的运算: 集合支持序列的相关运算,同时不一样的地方在于: 集合是不允许元素重复的,会自动清除相同元素,同时元素是有序的(默认从小到大),之前的元组以及列表都是无序的。 >>> {1,2,2} {1, 2} >>> {1,2,4,3,2} {1, 2, 3, 4} >>> {4,3,2,1} {1, 2, 3, 4} 集合支持减号:(除去集合中相同的项并返回到减号前面的集合)(差集) >>> {1,2,3}-{1} {2, 3} >>> {1,2,3}-{4} {1, 2, 3} >>> {1,2,3}-{2,3,4} {1} 集合支持并和与的计算(交集:&,并集:|): >>> {1,2,3}&{3} {3} >>> {1,2,3}|{4} {1, 2, 3, 4} 集合与字典: >>> type({}) <class 'dict'> 空集合的表示方法: >>> type(set()) <class 'set'> 空集合的长度: >>> len(set()) 0 字典是无序的,字典不属于序列,无法用下标的形式进行查询,但是字典存在key值,我们可以通过直接查询key值来查询相关元素: 键值key是不允许相同的,同时key可以是不同数据类型: >>> {1:2,1:3} {1: 3} >>> {1:2,'1':2} {1: 2, '1': 2} >>> {1:2,'1':3}['1'] 3 >>> {1:2,'1':3}[1] 2 这里需要注意的是:value值是可以任意的数据类型,比如str,int,float,tuple,甚至是list,set,dict,但是key值存在限制,key值只能是不可变对象,比如str,int,float,tuple等,可变对象就不可以是key值,比如list,set,dict。
8.系统关键字与引用的可变性和值的不可变性:
系统关键字也可以自定义但是系统关键字之前的功能就失效了 没有必要给自己挖这样的坑: >>> type=1 >>> type(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not callable >>> 1(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not callable >>> print(type) 1 当然上面也可以将type改为print,print就失去原来功能。 引用类型是可变的,赋值改变时不新增对象,只是对原来的对象进行改变,值类型是不可变的,值类型重新赋值时会新增一个对象。 上面注意引用类型的使用 >>> a=3 >>> id(a) 1687645280 >>> b=9 >>> a=a+b >>> print(a) 12 >>> id(a) 1687645568 >>> a=3 >>> id(a) 1687645280 >>> a=4 >>> id(a) 1687645312 对于str类型也是如此: (如下图) str由于是不可变类型,所以'python'[0]='o'是错误的。
9.逻辑运算符:
or and not : 或 且 非: 或只需一个真就不必往后进行判断了,且是需要判断到最后才能算出是否为真,因此结果如下: >>> not True False >>> 1 or 2 1 >>> 2 or 3 2 >>> 3 or 4 3 >>> 1 and 2 2 >>> 2 and 3 3
身份运算符(is)判断内存地址是否相等 相等返回True,反之返回False 判断类型: type(a)==int 如果a是整型返回True ,一般可用isinstance函数: instance(a,int) 如果a是整型返回True 当然也可以使用ininstance(a,(int,str,float))来进行判断,看a是否属于后面给出的其中一类。 对象的三个特征:id、value、type 判断:is,==,isinstance 位运算:先将十进制数转化为二进制数 按位与:只有二进制对应的位都为1时才为1,否则为零 按位或:二进制对应的位有1时就记为1
优先级:not>and>or 系统命令行cmd 调用D盘:D: dir显示目录 执行python文件时:python+文件名
10.分支,条件,循环,枚举,包,模块,函数:
''' 一般程序存在智能感知,回车键选中自己想要的即可 ''' # if else for while switch # 注释方法: ''' if else for while switch ''' ''' mood=True if mood: print('1') else: print('0') 输出:1 ''' ''' account = '123' password = '0000' user_account = input() user_password = input() print(user_account) if (account == user_account) and (password == user_password): print('success') else: print('false') 输入输出: 123 0000 success ''' ''' 对于常量,python是使用全部大写(规范)(实际在python中是不存在常量 这个概念的,这里只是指不变的量 对于运算符,标识符,以及缩进都比较严格 运算符:比如==,要左右都有空格 标识符:冒号:前面不要有空格,逗号,后面留一个空格(在元组,列表等可不用),注释#前面距离代码至少两个空格等 缩进:if else等注意缩进:Tab(四个空格) snippet elif相当于else if switch在python没有语法定义 字典的使用要强于elif input()函数每次都将接收到的变量认为是字符串 a=input() type(a)为字符串类型 要使a变为int整数型 使用:a=int(a) 例: a = input() print(type(a)) a = int(a) print(type(a)) if a == 1: print('success') 小应用: 当a与b一真一假时,我们要返回真可以使用if else语句实现,也可以使用or来实现 a or b 返回为真的一个 ''' ''' 循环语句: for while 解决无限循环方法: 上面工具栏Run stop终止程序 或者下面窗口栏右击程序 Close Tab while循环例: a = 1 while a <= 10: print(a) a += 1 else: print('EOF!') while可与else搭配 但是while与else搭配,for与else搭配并不常用,很多语言也没有这种语法 ''' ''' for循环例: b = ((1, 2, 3), [1, 3, 2]) for x in b: for y in x: if y == 2: print(y, end='abc\n') break print('bbb') print('aaa\n', end='') # print的end本来就默认打出回车键,不必继续打回车,这里将end改为空'' else: print('EOF!', end='\n12345678') 输出结果: bbb 2abc #跳出内循环 aaa bbb bbb 2abc #跳出内循环 aaa EOF! #for循环执行结束后执行else语句 12345678 ''' ''' # 当执行指定次数的循环时: # range()函数,左闭右开区间: for x in range(1, 11, 1): print(x, end=' ') # 执行结果:1 2 3 4 5 6 7 8 9 10 print('') # 由于内置回车,因此这里什么都不必输入就会打出一行空行 # 当然对于递增1位也可以不加后面的1: for x in range(1, 11): print(x, end=' ') print('') # 执行结果:1 2 3 4 5 6 7 8 9 10 for x in range(1, 11, 3): print(x, end=' | ') # 执行结果:1 | 4 | 7 | 10 | print('') for x in range(11, 1, -3): print(x, end=' | ') # 执行结果:11 | 8 | 5 | 2 | ''' ''' # range()函数与切片: # 对于上面的range()函数,如果又有给定的序列等可以使用,则可以搭配len()函数 a = [1, 2, 3, 4] # 指定序列 for x in range(0, len(a), 2): # 这里的len(a)只是获取长度,与序列内容无关 print(a[x], end=' ') # 执行结果(当上面是x而不是a[x]时):0 2 # 这里从0到4左闭右开 # 当是a[x]时:1 3 # 就是a[0],a[2]即1,3 # 我们也完全可以使用切片的方式来代替上面的for循环: # 三个参数,两个冒号,最后一个参数为步长 b = a[0:len(a):2] # 这里就是对序列直接进行切片 print(type(b)) # 这里b返回的不是序列内的元素,而是返回切片之前的序列类型 print(b) # 输出结果: # <class 'list'> # [1, 3] ''' ''' 会写代码很容易 高性能,封装性(可复用),抽象能力(编程是现实生活到计算机里的映射) 不要太直白 美与不美 ''' ''' Python组织结构: 包(物理表现:文件夹),模块(.py文件),类(java,C#认为一个文件就写一个类) 包:C#:dll,JAVA:jar包 包可以建立子包,当然包下面的模块也可以与子包同级 命名空间(文件路径) 模块: 首先要建立一个包,必须建立一个特殊的模块,模块名叫做__init__.py 如果没有这样一个特殊模块,python就会认为这只是一个普通的文件夹,而不是一个包 该文件可以什么都不写,只是标注这是一个包,当然也可以像普通文件一样编写代码 该文件名不是.__init__.py,而是包名 比如test包中该模块就叫test,而不是test.__init__.py 模块之间的调用: 注意命名空间的添加 一定是模块的调用(.py文件) 第一种导入(调用)形式: 模块调用从后往前调用,依次调用执行: 例: D:\untitled1\python\__init__.py 文件内代码如下: import python.c7 print(python.c7.a) print('__init__.py') b = input() print(b) D:\untitled1\python\c7.py 文件内代码如下: a = 1 print('123') # 该代码的调用就是先调用.c7后调用python # 执行过程如下: 123 # 首先执行c7 1 # 然后执行python,打出变量a,下一行继续打印 __init__.py 2 # 该行为input()输入的 2 # 调用过程结束,执行当下剩余代码 1 __init__.py b # 该行为input()输入的 b Process finished with exit code 0 再举一个例子: D:\untitled1\c6.py 文件内代码如下: import python.c7 print(python.c7.a) # 该代码的调用也是先调用.c7后调用python # 执行过程如下: 123 # 首先执行c7 1 # 然后执行python,打出变量a,下一行继续打印 __init__.py b # 该行为input()输入的 b # 调用过程结束,执行当下剩余代码 1 Process finished with exit code 0 # 根据上面两个例子告诉我们__init__.py文件在每次调用该包内文件时都会被自动调用 # 因此,__init__.py文件适合应用于模块的初始化(可进行对库的批量导入) 命名空间过长时,可以使用as来进行替代 例如上面的python.c7可以替换为c7或者任何简单的名字: 格式(这里将python.c7转换为c7):import python.c7 as c7 然后就可以使用了:例:print(c7.a) 第二种导入(调用)形式: from 包 import 对象/函数 然后直接使用这些变量名或者函数 当然也可以从包中导入文件,不过这样使用就跟直接使用import导入文件没有差别了 如果要导入全部变量,其实也可以这样使用: from 包 import * 以星号的形式导入全部变量 但是当我们使用这些变量时由于该文件中没有过出现这些变量名,系统会提示语法错误,但实际上仍然是可以运行的 模块的内置变量,模块的内置属性 __all__=['a', 'b'] 一定是字符串类型的 然后再利用*进行导入时只导入列表内存在的元素变量 也可以直接导入多个变量 from c7 import a, b, c 编译代码时会自动生成一些文件: 如:__pycache__文件夹以及.cpython-36.pyc等中间编译文件 如果是VScode编译器也可以在资源管理器进行隐藏这些文件 PyCharm编译器直接自动隐藏了 Python编码规范,一行尽量不要超过80个字符 如果要换行可以使用反斜杠\进行换行连接(不过不好看) 建议使用括号来换行 对库的批量导入: 对库的批量导入可放在该文件下然后对要导入该库的文件直接导入包即可(其实包名也就是该文件名) 批量导入不能重复导入(即不能循环导入) 有时候循环导入是不易发现的,可能涉及到多个文件之间导入的闭合,这就需要更细心一点 入口文件的概念 ''' ''' # 函数 IDLE内: help(函数名)即可查看函数内置操作 也可使用import this查看python之禅 比如round函数,保留到小数点后面几位(四舍五入原则) 例如: a = 1.123456 a = round(a, 2) print(a) a = round(a, 5) print(a) 当然上面的一段输出是有问题的,输出结果如下: 1.12 1.12 因为a = round(a, 2)这一步a就已经变成了1.12,然后继续执行是无法得到原来的a保留五位小数的结果的 改成下面的: a = 1.123456 b = round(a, 2) print(b) c = round(a, 5) print(c) 输出结果: 1.12 1.12346 可以看到round()函数默认为四舍五入 函数的使用: 1.功能性 2.隐藏细节(函数内部细节可能很复杂,但是在使用时不必看其内部结构) # 但是如果要深入学习或者函数内部出现了bug,我们就需要进入函数内部进行查看 3.避免编写重复的代码 也可以进行组织代码,但是面向对象对于组织代码更合适一些 可自定义函数 函数的定义: def关键字 函数名 (参数列表): 函数体 函数体内可以返回直接value,如果没有return,默认返回None空值 自定义函数名如果跟某些系统函数名冲突等容易造成函数循环调用 例: def print(code): print(code) 本来想要打印传入的参数,但是由于函数名的问题会造成一直调用自身,导致函数无限循环 但是Python也是非常的人性化,当函数循环调用执行到大概1000次左右时会自动停止程序并报错 当然我们也可以自定义进行设置最大递归次数 如何设置: import sys sys.setrecursionlimit(递归次数) # 这里的递归次数我们可以自由设定 当然python内部不会过于大了,由于计算机系统的原因也不会达到太大 例: a = 3 b = 2 def add(x, y): result = x + y return result print(add(a,b)) print(add(1, 2)) 输出: 5 3 有的函数存在可变参数:如系统的print()函数参数个数不确定 ''' ''' 序列解包: 元组索引解包操作(不推荐使用该解包方式,容易乱): 具体使用: 该处的3,6为随意输入的数据,对应的输出结果为9,22: 如下图:
下面的解包方式都是正确的(对应元素个数要相等): d = 1, 2, 3 print(type(d)) a, b, c = d print(a, b, c) a, b, c = [4, 5, 6] print(a, b, c) a = b = c = 1 print(a, b, c) 输出结果: <class 'tuple'> 1 2 3 4 5 6 1 1 1 ''' ''' 函数参数: 形式参数,实际参数(形参,实参):形参是定义时括号内的参数,实参是调用时括号内的参数 1.必须参数:定义了多少个形参就要传递多少个实参 2.关键字参数:对实参进行标注,然后可以随意调换实参顺序 例: 函数定义:def add(x,y): 函数调用:result = add(y = 3, x = 2) 3.默认参数:在形参上进行操作,当存在实参时,代入该实参,否则代入默认参数(一般传参数较多时使用,但是不推荐传入参数过多,当参数过多时可传入对象) 例: def test(z, x = 1, y = 2): print(x, y, z) test(3) 输出: 1 2 3 注意定义函数时必须传入的参数只能放到默认参数之前,即默认参数之后不可存在待传参数 例: def test(x = 1, y = 2, z): print(x, y, z) test(3) SyntaxError: non-default argument follows default argument 另外对于调用来说也可以使用关键字参数来进行指明传参量 但是对于关键值参数也是不可以将必须参数与默认参数的顺序随意混乱,仍然遵循默认参数之后不可存在必须参数(除非每个参数都是关键字参数) '''
11.面向对象基本知识:
''' 面向对象 有意义的面向对象的代码 有类不能等同于是面向对象 类的实例化 student = Student() 类最基本的作用:封装 类下面的函数一定要加self,否则会报错,而且在使用类内的变量时一定要加self,否则也会报错 建议类的模块内只写类,不写类的实例化与调用 如果写在一起代码结构会变得非常松散 方法和函数的区别:很多时候已经模糊了这两个概念: C,C++:函数,java,C#:方法 方法:更多的是面向对象的概念,面向对象更关注的是设计,设计代码结构,设计封装 因此方法更多的是设计层面的称谓 函数:更多的是面向过程的概念,没有设计层面的意义在里面 程序运行,过程式的一种称谓 类是现实世界或思维世界的实体在计算机中的反映 它将数据(数据成员)以及这些数据上的操作(方法)封装在一起 python内类构造函数在实例化时会自动调用 格式如下:def __init__(self): 默认返回为None,而且只能返回None,不能返回其他类型 要传入参数的话写在构造函数内,而且一旦确定就必须传入相应实参 构造函数:初始化对象的属性(特征) 等号左边为类内变量(数据成员),右边为形参名 数据成员与形参名可以相等 例: name = name 而不必非要写成name = name1或者name = name_等 之前讲到的模块部分局部变量与全局变量的作用域: 模块内局部变量不会覆盖全局变量 (函数的局部变量与模块的全局变量可重名) 类变量,实例变量的概念(见下面例题) python寻找机制: 如果要寻找实例变量,如果没有找到会到类变量内去寻找,如果还是没有找到,会到类的父类里面去寻找(继承) ''' ''' class Student: # 在这里Student后面也可以选择加上括号,但是加不加无所谓,加上在PyCharm中反而会提示多余的括号 name = 'MJG' age = 0 # 类变量 def __init__(self, name, age): self.name = name self.age = age # 实例变量(必须加上self)(当然self可以是任意的,只不过使用self是一种常用习惯) # 有了实例变量的概念,那么还有实例方法的概念(对象实例可以调用的方法) student = Student('1', '2') print(student.name) print(student.age) student = Student print(student.name) print(student.age) # 输出结果: # 1 # 2 # MJG # 0 ''' ''' # 如果代码是下面一段: class Student: name = 'MJG' age = 0 def __init__(self, name, age): name = name age = age student = Student('1', '2') print(student.name) print(student.age) # 输出结果: # MJG # 0 # 却并不是我们想要的'1', '2',这是因为在构造函数内没有标明self,导致变量只作用于局部 # 当输出时找不到对象变量就只能寻找类变量进行输出 ''' ''' 下面介绍一下变量__dict__(系统内置到对象中保存对象的所有变量): 可通过打印__dict__变量查看对象的所有变量,当然我们也可以打印该类变量打出类内的所有变量 例: class Student: name = 'MJG' age = 0 def __init__(self, name, age): self.name = name self.age = age student = Student('1', '2') print(student.name) print(student.age) print(student.__dict__) print(Student.__dict__) 输出结果: 1 2 {'name': '1', 'age': '2'} {'__module__': '__main__', 'name': 'MJG', 'age': 0, '__init__': <function Student.__init__ at 0x000001B3A9AD0048>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None} # 分别显示了所有的对象变量与类变量 ''' ''' Python类: 变量:类变量,实例变量 方法:实例方法,类方法,静态方法 特殊函数:构造函数 实例变量:访问实例变量在类内必须加上self,否则会出现误解,导致找不到实例变量 在类外可以直接调用 例: def __init__(self, name1, age1): self.name = name1 self.age = age1 print(self.name) # 调用实例变量(正确) print(name) # 既不是调用实例变量也不是调用类变量(类变量内虽然存在name变量,但是这并不是调用类变量的方式,依然会报错) print(name1) # 既不是调用实例变量也不是调用类变量(但是这里并不会报错,调用的是形参) # 调用类变量的两种方法: print(Student.name) # 访问类变量(类内类外都可以这样调用) print(self.__class__.name) # 类变量的调用(类内) 对于类内变量的操作: class Student: name = 'MJG' age = 0 sum = 0 def __init__(self, name1, age1): self.name = name1 self.age = age1 print('name:' + self.name) print('age:' + self.age) self.__class__.sum += 1 print('当前sum数:' + str(self.__class__.sum)) student = Student('1', '2') student__ = Student('3', '4') print('最后类变量sum:' + str(Student.sum)) 输出: name:1 age:2 当前sum数:1 name:3 age:4 当前sum数:2 最后类变量sum:2 类方法: 对于类变量我们可以在构造函数或实例方法中进行操作,当然我们完全可以通过类方法来进行操作: 一般来说,对于类变量的操作我们都是放在类方法中去执行,而不是构造函数与实例方法 定义: 标志(装饰器):@classmethod 类方法代表名:cls(参数列表内),也像实例方法一样可以更改,但是也是一种习惯性表达 例: class Student: sum = 0 @classmethod def sum_(cls): cls.sum += 1 print(cls.sum) Student.sum_() # 类方法就要使用类去调用 但是python也是允许对象去调用类方法的,但是这在实际上是说不通的,一般不建议使用这种方法 # student = Student # student.sum_() 输出结果: 1 静态方法: 定义: 标志(装饰器):@staticmethod 类方法与实例方法、类方法的区别: 静态方法没有像实例方法、类方法那样要求强制传入一个默认指定的名字,类方法的cls代表的是类本身,实例方法的self代表的是实例本身 静态方法没有这样一个默认传入,只是一个普普通通的方法 总结: 类访问类变量(OK),实例变量(也OK) 对象访问类变量,实例变量,都OK 类与对象都可以访问静态方法 类方法,实例方法,静态方法之间的相互访问: 类方法与静态方法都不可以访问实例变量 实例方法与静态方法都可以访问类变量 一般不建议使用静态方法,除非使用的方法非常纯粹,与类和对象都没有太大的关联 ''' ''' class Student: sum = 0 def __init__(self, name1, age1): self.name = name1 self.age = age1 # 自动为对象创建新变量sum def __sum__(self): self.sum += 1 print(self.sum) # 结果由{'name': 'MJG', 'age': '20'}变为: # {'name': 'MJG', 'age': '20', 'sum': 1} student = Student('MJG', '20') print(student.__dict__) student.__sum__() print(student.__dict__) # 输出: # {'name': 'MJG', 'age': '20'} # 1 # {'name': 'MJG', 'age': '20', 'sum': 1} ''' ''' *** class Student: sum = 0 def __init__(self, name1, age1, test1, test2): self.name = name1 self.age = age1 self.test = test1 # 公开 self.__test = test2 # 私有,这里允许重名(一个私有,一个公开) self.__class__.test = 10 # 调用类变量,如果一开始没有选择创建 Student.__test = 20 # 调用类变量,如果一开始没有选择创建(允许重名)(两种不同的调用类变量的方式) # 前面加两条下划线,变为私有,类外直接调用该方法会报错 def __sum(self): self.sum += 1 print(self.sum) print(Student.__dict__) # 最初始时,只有一个sum变量 student = Student('MJG', '18', 'test1', 'test2') print(student.__dict__) # 注意到test是公开的,__test是私有的:{'name': 'MJG', 'age': '18', 'test': 'test1', '_Student__test': 'test2'} student.__test = 100 # 对象内虽然存在test私有变量,但是这里并不是正确的访问私有变量的方式 # 而且就算可以这样访问,也不能更改私有变量,因为这两个类型本身就是不同的,不能赋值,这里是类外为对象创建了新变量__test print(student.__test) # 并不是可以访问私有成员(访问私有成员的方式也不是这样),而是上一行已经为对象创建了新变量__test(如果上一行没有创建过程是会报错的) print(student.__dict__) # 加上构造时的test(test1)和__test(私有)(test2)以及新创建的__test变量(形式,并非私有):{'name': 'MJG', 'age': '18', 'test': 'test1', '_Student__test': 'test2', '__test': 100} # 对类变量: print(Student.__dict__)# 在构造时就已经创建了新的类变量:公开变量:test和私有变量__test(仅测试用) # {'__module__': '__main__', 'sum': 0, '__init__': <function Student.__init__ at 0x000002BD60FF0048>, '_Student__sum': <function Student.__sum at 0x000002BD60FF01E0>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, 'test': 10, '_Student__test': 20} # 对对象进行再创建与测试: student1 = Student('test_name', 'test_age', 'test1.1', 'test2.1') print(student1.__dict__) # print(student1.__test) # 这里不对其进行创建,是会报错的 print(Student.__dict__) # 输出: # {'name': 'test_name', 'age': 'test_age', 'test': 'test1.1', '_Student__test': 'test2.1'} # {'__module__': '__main__', 'sum': 0, '__init__': <function Student.__init__ at 0x000002548D330048>, '_Student__sum': <function Student.__sum at 0x000002548D3301E0>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, 'test': 10, '_Student__test': 20} 强制读取私有数据成员: print(student._Student__test) print(student1._Student__test) print(Student._Student__test) # 上面的方法是可以的,但是强行读取类就没有了意义(python的保护机制是比较弱的,比较简单) 输出: test2 test2.1 20 ''' ''' 面向对象的三大特征: 继承,封装,多态: 继承: 一、首先导入一个模块(一般不用这种方式) import 模块名 class Student(模块名.类名): 二、直接导入模块下的类 from 模块名 import 类名 class Student(类名): 继承后构造: 首先要传入父类构造函数内的参数 一、显示调用父类的构造函数 二、(一般这样操作):super关键字:super(子类名, self).__init__(父类构造函数参数表) (调用父类的方法:super(子类名, self).方法名) 子类内方法可与父类内方法名重名并进行覆盖 '''
12.运算符优先级问题:
13.代码自动调节工具pep8:
写一个有用的代码自动调节工具: pep8: 安装方法: 首先在系统命令行输入: python -m pip install autopep8 系统会自动下载安装autopep8 根据提示进行更新等操作即可完成安装,然后配置autopep8
14.python库的安装:
一、(三个python通用的,不过没试过) 下载编译好的python扩展库(不过好像停用了)(可以百度一下,很多类似的库)(一般pip或者搭配镜像即可): http //www lfd.uci.edu/~gohlke/pythonlibs/ 下载完毕后直接解压放入: C:\Python27\Lib\site-packages(对应自己的库) 就可以import使用了。 大部分库都是有的,特别是机器学习类的,很全。 二、cmd pip python -m pip install 包名 三、Anaconda直接安装
15.解决pip超时问题:
解决pip超时问题: 问题状况如下: raise ReadTimeoutError(self._pool, None, "Read timed out.") pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out. 一、(实验可用有效) 解决办法(采用镜像下载)://例如这里采用豆瓣镜像,下载wordcloud词云库: //下载什么库就在pip install -i https://pypi.douban.com/simple后面写什么 pip install -i https://pypi.douban.com/simple wordcloud 国内镜像源: http://pypi.douban.com/ 豆瓣 http://pypi.hustunique.com/ 华中理工大学 http://pypi.sdutlinux.org/ 山东理工大学 http://pypi.mirrors.ustc.edu.cn/ 中国科学技术大学 二、(可用但未尝试) 可对pip进行时间限制,在指定时间限制内忽略中停止问题(加大下载时间)
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!
赞 (0)