Python基础学习笔记

时间:2022-05-07
本文章向大家介绍Python基础学习笔记,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

---------2018.1.24------------

round是向上取整,引用方式为round(number[,ndigits])

而floor是向下取整,floor函数通过import math导入,引用方式为math.floor(number)

str函数,它会把值转换成合理形式的字符串,函数原型为str(object)//字符串要用双引 号引起来,数字不需要

repr函数,它会创建一个字符串.以合法的Python表达式的形式来表示值,函数原型为repr (object)

如果你希望打印一个包含数字的句子,加上``(反引号)可以很方便的输出

input()与raw_input()区别

input()会假设用户输入的是合法的python表达式,例如字符串一定要用引号引起来

而raw_input()会把所有的输入当作原始数据将其放入字符串中

如果你需要写一个非常长的字符串,需要跨越多行,可以使用三个引号(单引号和双引号均 可)代替.

如果一行中最后一个字符是反斜杠,那么换行符本身就"转义"了,也就是被忽略了.

原始字符串r'x'或者r"x",几乎可以输出任何字符,唯一不行的就是原始字符串最后的一个 字符不能是反斜杠,要输出反斜杠,只有对原反斜杠进行转义,形式为'\'

pow(x,y[,z]) 返回x的y次幂(所得结果对z取模)

---------2018.2.6------------

利用切片操作,实现一个trim()函数,去除字符串首尾的空格,注意不要调用str的strip()方法

 1 # -*- coding: utf-8 -*-
 2 def trim(s):
 3     if s[:1] != ' ' and s[-1:] != ' ':
 4         return s
 5     elif s[:1] == ' ':
 6         return trim(s[1:])
 7     else:
 8         return trim(s[:-1])
 9 # 测试:
10 if trim('hello  ') != 'hello':
11     print('测试失败!')
12 elif trim('  hello') != 'hello':
13     print('测试失败!')
14 elif trim('  hello  ') != 'hello':
15     print('测试失败!')
16 elif trim('  hello  world  ') != 'hello  world':
17     print('测试失败!')
18 elif trim('') != '':
19     print('测试失败!')
20 elif trim('    ') != '':
21     print('测试失败!')
22 else:
23     print('测试成功!')

汉诺塔的移动可以用递归函数非常简单地实现。

请编写move(n, a, b, c)函数,它接收参数n,表示3个柱子A、B、C中第1个柱子A的盘子数量,然后打印出把所有盘子从A借助B移动到C的方法,例如:

1 def move(n,a,b,c):
2     if(n==1):
3         print(a,'-->',c)
4     else:
5         move(n-1, a, c, b)
6         move(1, a, b, c)
7         move(n-1, b, a, c)
8 move(3, 'A' , 'B', 'C')

 请使用迭代查找一个list中最小和最大值,并返回一个tuple:

 1 # -*- coding: utf-8 -*-
 2 def findMinAndMax(L):
 3     length=len(L)
 4     if(length==0):
 5         return (None,None)
 6     elif(length==1):
 7         return (L[0],L[0])
 8     else:
 9         minn=L[0]
10         maxn=L[0]
11         for x in L:
12             if(x>=maxn):
13                 maxn=x
14             if(x<=minn):
15                 minn=x
16     return (minn,maxn)
17 # 测试
18 if findMinAndMax([]) != (None, None):
19     print('测试失败!')
20 elif findMinAndMax([7]) != (7, 7):
21     print('测试失败!')
22 elif findMinAndMax([7, 1]) != (1, 7):
23     print('测试失败!')
24 elif findMinAndMax([7, 1, 3, 9, 5]) != (1, 9):
25     print('测试失败!')
26 else:
27     print('测试成功!')

杨辉三角定义如下:

          1
         / 
        1   1
       /  / 
      1   2   1
     /  /  / 
    1   3   3   1
   /  /  /  / 
  1   4   6   4   1
 /  /  /  /  / 
1   5   10  10  5   1

把每一行看做一个list,试写一个generator,不断输出下一行的list:

 1 # -*- coding: utf-8 -*-
 2 def triangles():
 3     a = [1] 
 4     while True: 
 5         yield a 
 6         a = [sum(i) for i in zip([0] + a, a + [0])]
 7 
 8 # 期待输出:
 9 # [1]
10 # [1, 1]
11 # [1, 2, 1]
12 # [1, 3, 3, 1]
13 # [1, 4, 6, 4, 1]
14 # [1, 5, 10, 10, 5, 1]
15 # [1, 6, 15, 20, 15, 6, 1]
16 # [1, 7, 21, 35, 35, 21, 7, 1]
17 # [1, 8, 28, 56, 70, 56, 28, 8, 1]
18 # [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
19 n = 0
20 results = []
21 for t in triangles():
22     print(t)
23     results.append(t)
24     n = n + 1
25     if n == 10:
26         break
27 if results == [
28     [1],
29     [1, 1],
30     [1, 2, 1],
31     [1, 3, 3, 1],
32     [1, 4, 6, 4, 1],
33     [1, 5, 10, 10, 5, 1],
34     [1, 6, 15, 20, 15, 6, 1],
35     [1, 7, 21, 35, 35, 21, 7, 1],
36     [1, 8, 28, 56, 70, 56, 28, 8, 1],
37     [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
38 ]:
39     print('测试通过!')
40 else:
41     print('测试失败!')
1 # -*- coding: utf-8 -*-
2 L1 = ['Hello', 'World', 18, 'Apple', None]
3 L2 = [s.lower() for s in L1 if isinstance(s,str)==True]
4 # 测试:
5 print(L2)
6 if L2 == ['hello', 'world', 'apple']:
7     print('测试通过!')
8 else:
9     print('测试失败!')

 split翻译为分裂。  split()就是将一个字符串分裂成多个字符串组成的列表。

split()当不带参数时以空格进行分割,当代参数时,以该参数进行分割。

//---当不带参数时

example:

st0= '   song    huan     gong    '

print(st0.split())

结果为:

['song', 'huan', 'gong']

结论:当不带参数时,默认是以空格作为参数,不管空格在哪,或者有几个 全部被镐掉了!

//---当带参数时 这种情况就不能按照上面的方式去理解了

example:

st0= 'iisongiiihuaniiiigongi'

print(st0.split('i'))

结果为:

['', '', 'song', '', '', 'huan', '', '', '', 'gong', '']

分析:  

  这个结果可能就有点出乎意料了并不是想象中的['song', 'huan', 'gong'] 而是多了很多空字符串元素'',这个怎么理解呢?    我的理解方式是,当带参数时,我们得把字符串想象成一块五花肉,我们要做 一件奇葩的事情,就是将肥肉丢到垃圾桶,把瘦肉留下。  比如'iisongiiihuaniiiigongi'这串五花肉,'i'就是要丢掉的肥肉,每次还只能切 'i'这么多。  切的时候是从左到右,一刀下去肥肉'i'丢掉,刀刃左边的部分拿走作为list的一个元素, 刀刃右边的就是剩下的,那么继续切剩下的部分,直到切完。

 'iisongiiihuaniiiigongi'这块肉比较特殊:  

  其一、他的开始和结尾都有i,而且i还不止一个!这样按照上述的方法就会切出 空气,就是列表中我们看到的'', 空字符串元素。    如'iisongiiihuaniiiigongi',当第一刀下去的时候,第一个i被丢到了垃圾桶, 而刀刃的左边什么都没有,所以列表的第一个元素就是'',空字符串元素。  一刀下去之后,就剩下'isongiiihuaniiiigongi'。  所以第二刀下去之后,又得到一个空字符串元素,目前“肉”就剩下'songiiihuaniiiigongi'。  第三刀又切掉一个i,那么刀刃左边的就是song,所以第三个元素就是'song'。    直到切到最后,整坨肉就只剩下一个i了,使用最后一刀下去i被切掉了,刀刃的左边此时也 什么都没有了,所以最后一个元素任然是空字符串。  

一个超级好的例子:

1 >>> str="hello boy<[www.doiido.com]>byebye"
2 >>> str.split("[")[1].split("]")[0]
3 'www.doiido.com'
4 >>> str.split("[")[1].split("]")[0].split(".")
5 ['www', 'doiido', 'com']

利用mapreduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456

 1 # -*- coding: utf-8 -*-
 2 from functools import reduce
 3 DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
 4 def char2num(s):
 5     return DIGITS[s]
 6 def str2float(s):
 7     s=s.split('.')
 8     if len(s[0])==0:
 9         s[0]='0'
10     return reduce(lambda x,y:x*10+y,map(char2num,s[0]))+reduce(lambda x,y:x*10+y,map(char2num,s[1]))*pow(0.1,len(s[1]))
11 print('str2float('123.456') =', str2float('123.456'))
12 if abs(str2float('123.456') - 123.456) < 0.00001:
13     print('测试成功!')
14 else:
15     print('测试失败!')

Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积:

1 # -*- coding: utf-8 -*-
2 from functools import reduce
3 def prod(L):
4     return reduce(lambda x,y:x*y,L)
5 print('3 * 5 * 7 * 9 =', prod([3, 5, 7, 9]))
6 if prod([3, 5, 7, 9]) == 945:
7     print('测试成功!')
8 else:
9     print('测试失败!')

利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']

1 # -*- coding: utf-8 -*-
2 def normalize(name):
3     name=name[0].upper()+name[1:].lower()
4     return name
5 # 测试:
6 L1 = ['adam', 'LISA', 'barT']
7 L2 = list(map(normalize, L1))
8 print(L2)

 回数是指从左向右读和从右向左读都是一样的数,例如12321909。请利用filter()筛选出回数:

 1 # -*- coding: utf-8 -*-
 2 def is_palindrome(n):
 3     nn = str(n) #转成字符串
 4     return nn == nn[::-1] #反转字符串并对比原字符串返回true/false
 5 # 测试:
 6 output = filter(is_palindrome, range(1, 1000))
 7 print('1~1000:', list(output))
 8 if list(filter(is_palindrome, range(1, 200))) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]:
 9     print('测试成功!')
10 else:
11     print('测试失败!')

 ---------2018.2.7------------

请把下面的Student对象的gender字段对外隐藏起来,用get_gender()set_gender()代替,并检查参数有效性:

 1 # -*- coding: utf-8 -*-
 2 class Student(object):
 3     def __init__(self, name, gender):
 4         self.name = name
 5         self.gender = gender
 6     def get_gender(self):
 7         return self.gender
 8     def set_gender(self,gender):
 9         if gender=='male' or gender=='female':
10             self.gender=gender
11         else:
12             raise ValueError('gender error')
13 # 测试:
14 bart = Student('Bart', 'male')
15 if bart.get_gender() != 'male':
16     print('测试失败!')
17 else:
18     bart.set_gender('female')
19     if bart.get_gender() != 'female':
20         print('测试失败!')
21     else:
22         print('测试成功!')

 2018/3/5

ubuntu16.04自带python的环境,不用进行python环境安装, 在安装好环境的虚拟机中,提供了py2,py3,django_py2,tornado_py2,spider_py2,django_py3的虚拟环境

mysql安装 sudo apt-get install mysql-server sudo apt-get install libmysqlclient-dev 注意安装server端的时候会提示输入密码,记住这个密码。然后通过命令登入数据库

redis安装 sudo apt-get install redis-server 通过redis-cli登入 mongoDB安装 详情请参考 http://blog.csdn.net/zgf19930504/article/details/52045600 postgresql安装 sudo apt-get install postgresql sudo apt-get install libpq-dev elasticsearch安装(django项目使用) sudo apt-get install elasticsearch 其它依赖包 sudo apt-get install python-dev

3.django环境安装 我们将虚拟环境所需的包全部放在install.txt,以下是django_py3项目所需环境: django==1.7.4 jsonfield Pillow==2.8.2 celery amqp==1.4.9 anyjson==0.3.3 billiard==3.3.0.23 celery==3.1.23 decorator==4.0.10 Django==1.7.8 django-haystack==2.5.0 django-redis-sessions==0.5.6 ipdb==0.8.1 ipython-genutils==0.1.0 jsonfield==1.0.3 kombu==3.0.35 psycopg2==2.6.2 pytz==2016.6.1 redis==2.10.5 setuptools==25.1.0 wheel==0.29.0 执行pip3 install -r instal.txt命令即可

4.tornado环境安装 在tornado_py2虚拟环境中安装: ipython==4.2.0 ipython-genutils==0.1.0 pingpp==2.0.11 pycrypto==2.6.1 qiniu==7.0.7 redis==2.10.5 requests==2.10.0 tornado==4.3 MySQL-python==1.2.5 SQLAlchemy==1.0.14

5.spider环境安装 在spider_py2虚拟环境中安装: attrs==16.0.0 backports-abc==0.4 backports.ssl-match-hostname==3.5.0.1 BeautifulSoup==3.2.1 beautifulsoup4==4.4.1 boto==2.38.0 certifi==2016.2.28 cffi==1.7.0 chardet==2.3.0 CherryPy==3.5.0 click==6.6 cryptography==1.4 cssselect==0.9.2 cssutils==1.0 Cython==0.24 decorator==4.0.6 Django==1.8.7 dnspython==1.12.0 easydict==1.6 enum34==1.1.6 feedparser==5.1.3 greenlet==0.4.10 html5lib==0.999 idna==2.1 ipaddress==1.0.16 ipython==2.4.1 jieba==0.38 jsonpath==0.54 lxml==3.5.0 Markdown==2.6.6 mechanize==0.2.5 motor==0.2 motorengine==0.9.0 mysqlclient==1.3.7 ndg-httpsclient==0.4.0 netifaces==0.10.4 nltk==3.2.1 parsel==1.0.2 pbr==1.9.1 pexpect==4.0.1 Pillow==3.3.0 pip==8.1.2 pkg-resources==0.0.0 poster==0.8.1 ptyprocess==0.5 pyasn1==0.1.9 pyasn1-modules==0.0.8 pybloomfilter==1.0 pybloomfiltermmap==0.3.12 pycparser==2.14 pycrypto==2.6.1 PyDispatcher==2.0.5 Pygments==2.1 pymongo==2.7 pyOpenSSL==16.0.0 python-dateutil==2.4.2 pytz==2014.10 PyYAML==3.11 queuelib==1.4.2 redis==2.10.5 repoze.lru==0.6 requests==2.10.0 Routes==2.2 rq==0.6.0 Scrapy==1.1.0 scrapy-redis==0.6.3 scrapyd==1.1.0 scrapyd-client==1.0.1 selenium==2.53.6 service-identity==16.0.0 setuptools==25.1.0 simplegeneric==0.8.1 singledispatch==3.4.0.3 six==1.10.0 sqlparse==0.1.18 stevedore==1.13.0 tornado==4.3 Twisted==16.2.0 urllib3==1.13.1 w3lib==1.14.2 WebOb==1.5.1 wheel==0.29.0 zope.interface==4.2.0

编译C语言代码(基于Vim编辑器)

vi 1.c i插入代码 上下左右还是可以使用HJKL或者up down left right(建议使用HJKL) 写完保存退出ESC+:x gcc 1.c编译 会生成a.out文件 运行a.out文件命令:./a.out

python3支持中文编码,python2不支持中文编码 要解决python2不支持中文编码的操作为: # -*- coding=utf-8 -*-

特别注意: python2中input的意思是把交互式输入的东西当成代码去执行,而python3中默认当作字符串去输入 而如果要让python2中输入的东西当作字符串,我们需要用到raw_input()

比如a=input("请输入你的名字:") 请输入你的名字:laowang python2中会报错,python3则不会 请输入你的名字:1+2 print(a) python2中打印结果为3 python3中打印结果为'1+2' 而python2中要实现打印字符串,用raw_input函数 a=raw_input("请输入你的名字:") 请输入你的名字:1+2 print(a) '1+2'

由于在python3中默认input类型为字符串类型,如果我们需要获取int类型,我们需要设置一个变量去存储字符串类型 例如age_num=int(age)

变量名不能使用关键字

import keyword keyword.kwlist 显示当前版本的所有关键字

print("%d%s%f"%(a,b,c))

不等于在python2和python3中通用写法是!= 但是在python2中还有一种写法是<>,这个意思也是表示不等于

vi编辑代码的时候,如果之前有定义的变量,敲完该变量的一部分,再敲上Ctrl+n自动补全

if not (条件):  print(xxx) 意思是不在条件范围内 if not (x>0 and x<50):  print("hello")

逻辑运算符: and 且 or  或 not 非

if 条件1:    print(a) elif 条件2:    print(aa) ...... else:    print(aaa)

while 条件:       a=b+c       print(c) 打印不换行:print("xxx(打印信息)",end="") 打印换行:print("")

复合赋值运算符: += -= *= /= %= **= //= 而不能使用j++之类的,这是错误的语法,只能写成j+=1

在进行复合赋值运算时,=后面的数字不管进行什么运算,切记加上小括号

举个例子: a=2 a*=3+2 答案是10,计算方式是a=a*(3+2)=2*5=10,而并不是a=2*3+2=8

import random random.randint(0,2) 意思是导入一个random的库,random.randint(0,2)意思是随机生成0-2中的整数

切片: name[2:6] 取的是从第二个位置开始(下标从0开始),到小于第六个位置为止(第五个位置)

name[2:] 取的是从第二个位置开始(下标从0开始),取到最后一个

name[2:-1:2] 取的是从第二个位置开始(下标从0开始),取到最后一个的前面一个,步长为2,就是每两个位置取一个

切片:[起始位置:终止位置:步长](针对字符串而言)

起始位置取大于等于号,终止位置取小于号

步长可以为负数

步长为负数时是倒着取值,反向,相当于取逆序数

find函数,意思是找到我们需要的字符串的首字符的下标,找不到输出-1

str="hello world" str.find("world") >>6 str.find("Hello") >>-1

index函数 和find查找函数一样 找到了返回 只不过find没找到返回-1 index没有找到直接返回异常

rindex 返回子字符串 str 在字符串中最后出现的位置 如果没有匹配的字符串会报异常

rfind 返回字符串最后一次出现的位置,如果没有匹配项则返回-1

count 用于统计字符串里某个字符出现的次数。可选参数为在字符串搜索的开始与结束位置。

replace 把字符串中的 old(旧字符串) 替换成 new(新字符串),如果指定第三个参数max,则替换不超过 max 次。

split 通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串 str.split(str="", num=string.count(str)). str -- 分隔符,默认为所有的空字符,包括空格、换行(n)、制表符(t)等 num -- 分割次数

str = "Line1-abcdef nLine2-abc nLine4-abcd"; print str.split( ); >>['Line1-abcdef', 'Line2-abc', 'Line4-abcd']

capitalize 将字符串的第一个字母变成大写,其他字母变小写。对于 8 位字节编码需要根据本地环境。

s = ' a, B'    # a 前面有空格 s.capitalize() >>' a, b'

title 所有单词都是以大写开始,其余字母均为小写 str.title()

startswith 用于检查字符串是否是以指定子字符串开头,如果是则返回 True,否则返回 False。如果参数 beg 和 end 指定值,则在指定范围内检查。

endswith 用于判断字符串是否以指定后缀结尾,如果以指定后缀结尾返回True,否则返回False。可选参数"start"与"end"为检索字符串的开始与结束位置。

lower 转换字符串中所有大写字符为小写 str.lower()

upper 将字符串中的小写字母转为大写字母 str.upper()

rjust 返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串。如果指定的长度小于字符串的长度则返回原字符串。

ljust 返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串。如果指定的长度小于原字符串的长度则返回原字符串。

center 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串。默认填充字符为空格。

lstrip 用于截掉字符串左边的空格或指定字符

rstrip 删除 string 字符串末尾的指定字符(默认为空格)

strip 用于移除字符串头尾指定的字符(默认为空格)

partition 用来根据指定的分隔符将字符串进行分割。

rpartition 从后往前查找,返回包含字符串中分隔符之前、分隔符、分隔符之后的子字符串的tuple;如果没找到分隔符,返回字符串和两个空字符串

splitlines 字符串以换行符为分隔符拆分,去掉换行符;如果keepends为True,保留换行符

isalpha 检测字符串是否只由字母组成

isdigit 检测字符串是否只由数字组成

join 用于将序列中的元素以指定的字符连接生成一个新的字符串

str = "-"; seq = ("a", "b", "c"); # 字符串序列 print str.join( seq ); >>a-b-c

append 用于在列表末尾添加新的对象 如果添加的对象是列表 则会整体添加 list.append(obj)

ps: a=[1,2] b=[3,4] a.extend(b) >>[1,2,3,4] a.append(b) >>[1,2,[3,4]]

insert 用于将指定对象插入列表的指定位置

list.insert(index, obj)

extend 用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)

list.extend(seq)

pop 用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值  删除最后一个 list.pop(obj=list[-1])

remove 用于移除列表中某个值的第一个匹配项   根据内容来删除

list.remove(obj)

del xxx[下标]  根据下标来删除

in 操作符用于判断键是否存在于列表/字典中,如果键在列表/字典里返回true,否则返回false

not in 如果在指定的序列中没有找到值返回 True,否则返回 False。

字典通过键来查找

info={键1:值1,键2:值2,......}

添加

xxx[新的key] = value

删除

del xxx[key]

修改

xxx[已存在的key] = new_value

查询

xxxx.get(key)

for...else结构:

如果for循环里面有break,不触发else 如果for循环里面没有break 一定会触发else

append 注意点: a=[1,2] b=[3,4]

a=a.append(b) 进行这一步操作后,a的值为None了

原因是进行a.append(b)操作后,b的值已经添加到a里面去了 结果已经发生变化了 但是我们单独敲a.append(b)这句话时, 并没有任何输出 这就说明a.append(b)这步操作的值为空 a.append(b)整体结果为没有 没有输出就没有结果 反而你把这个传入a a的值只能保存为空 即为None

在python2中

keys 以列表返回一个字典所有的键

ps:dict.keys()

values 以列表返回字典中的所有值

ps:dict.values()

items 以列表返回可遍历的(键, 值) 元组数组

ps:dict.items()

而python3中

会返回一个生成器 一个对象 内容是列表的形式

example:

在python2中: info={"name":"laowang","age":18} info.keys() >>['name','age']

而在python3中 info={"name":"laowang","age":18} info.keys() >>dict_keys(['name','age'])

拆包

举个例子就知道了: 下面是元组拆包 a=(11,22) c,d=a c >>11 d >>22

在items中取值时,两种取值方式 一种是用数组下标 一种是元组拆包

举个例子: info={"name":"laowang","age":18} for temp in info.items():     print("key=%s,value=%s"%(temp[0],temp[1]))

info={"name":"laowang","age":18} for A,B in info.items():     print("key=%s,value=%s"%(A,B))

以上两种方式得出的结果相同

元组:(小括号)

字典:很多信息描述一个物体(大括号) 列表:存储不同物体的相同信息(中括号)

元组类型的数据不能修改里面的值,相当于一个只读文件 而列表可以修改值

函数: def 函数名:        ...

一个函数想要返回多个数值,可以将其打包成元组或者列表

return a,b,c 相当于封装成元组返回

写代码规范: 写函数时,先写结构,再去考虑里面内容

代码能够重复使用

全局变量与局部变量注意点:

1.如果全局变量中定义了某个量 如果还想在函数中对这个变量进行修改的话 在函数中使用global对全局变量进行一个声明 那么这个函数中的变量就不是定义一个局部变量 而是对全局变量进行修改

2.全局变量定义得放在函数调用之前

#注释会被忽略 文档字符串(doctoring)"""XXX"""可以被调用(不影响程序的执行)

def main 完成对整个程序的控制 main函数需要定义

main()调用主函数

python代码一般格式: # -*-coding=utf-8-*- import xxx def xxx(aa):       ... xxx(aa)

列表 字典的注意事项:

如果列表 字典当作全局变量 可以不需要在函数中定义global,加了也没事 但是单纯的变量在函数中一定需要加上global

缺省参数:在函数中传入默认值 在调用函数时可以不传入那个变量值 那个参数称为缺省参数

example: def test(a,b=22):     result = a+b     print("result=%d"%result) test(11) test(22,33) test(44)

>>33 >>55 >>66

而像test(11,b=22) b=22为命名参数

不定长参数

如果我们需要调用一个传入任意个参数的函数 怎么办呢 我们这时候采用传入*args 函数的形参 告诉python解释器 传入的实参个数如果大于形参真正的个数 剩下的统统扔给args 比如我们有10个苹果要分给三个人 有个人是你的亲属 需要你照顾他 每个人发完一个后 剩余的都给需要照顾的人

输出的结果为元组

example: def sum(a,b,*args):     print(a)     print(b)     print(args)

sum(1,2,3,4,5,6,7,8) >>1 >>2 >>(3,4,5,6,7,8)

对于上面这个例子 如果传入的实参只有2个 也不会错 args的值为空 输出的时候会输出一个()(空的元组)

**kwargs 以字典的形式保存 输出结果为字典形式

多余参数不带变量名的 统统给args 多余参数带变量名的 统统给kwargs

def sum(a,b,*args,**kwargs):     print(a)     print(b)     print(args)     print(kwargs)

sum(1,2,3,4,5,6,task=88,done=78)

1 2 (3, 4, 5, 6) {'task': 88, 'done': 78}

拆包:

就是在实参上加上*/** 把一个列表/字典拆成一个一个值 元组/列表拆成一个一个元素 字典拆成 key value 这个过程就是拆包

用法:如下例子

def sum(a,b,*args,**kwargs):     print(a)     print(b)     print(args)     print(kwargs)

A=(44,55,66)/[44,55,66]

B={"name":"laowang","age":18}

sum(11,22,*A,**B) 在实参上写了*/** 意思是拆包

>> 11 22 (44, 55, 66) {'name': 'laowang', 'age': 18}

id 用于获取对象的内存地址 id([object])

a=1 意思并不是说定义了一个变量 而是贴了个标签,这个标签是内存地址

b=a 这个意思也是把a的内存地址给b 所以id查看会发现a,b的内存地址相同

而C语言不是 C语言是定义变量 只是值相等 地址不同

只要a的值改变了 b的值也会改变

python有自动回收垃圾机制

数字是不可变类型 字符串也是不可变类型 元组也是个不可变类型

举个例子 a="hello" a[0] >>'h' a[0]='H' 报错。。。

说明字符串不允许修改

列表和字典属于可变类型 在定义时不允许当key用

infors.sort(key=lambda x:x['name'])

匿名函数 lambda

eval 用来执行一个字符串表达式,并返回表达式的值

eval(expression[, globals[, locals]])

交换两个数

a=a+b b=a-b a=a-b

任何语言都适用

a,b=b,a python独特写法 两数交换

列表加上列表 等于 列表的合并

误区:

python里面不是值赋值,而是引用赋值

例子:

num+=num与num=num+num的区别

由于python里面时引用赋值 假设num=100传入一个求解两个数的和的函数

num+=num 传入的实参num指向100这个值

所以做修改时直接修改的是num本身的值

修改的是全局变量

而num = num + num 传入参数时 num定义的是临时变量

此时num指向的是100+100=200

文件的读入

f = oepn("test.py","r") 意味着通过open打开文件 用f进行操作文件的读写

r 文件必须存在 w 文件如果不存在 就创建新文件 a 打开一个文件 从文件的末尾写

rb wb ab 有b结尾说明是二进制文件

文本文件与二进制文件区别

r+ w+ a+ +表示你可以读写文件

rb+ wb+ ab+

open默认以读入的方式打开 所以可以不写"r"

seek 用于移动文件读取指针到指定位置

fileObject.seek(offset[, whence])

f.seek(2,0) 0表示文件的开头 2表示跳过开头两个位置开始读

如果我已经读完了一个文件 想要重新读取该文件

我们应该用f.seek(0,0)拉回来 让该文件还能调用f.read()重新读取

f.tell() 返回文件的当前位置,即文件指针当前位置

fileObject.tell(offset[, whence])

open 支持相对路径和绝对路径

面向过程 考虑要面面俱到 强调的是过程 而面向对象则不需要 找个有这样能力的人去做 强调的是对象

形象的解释 对象 看的见摸得着 实实在在的东西

类是模型 一个概念

类由三部分组成

类的名称:类名

类的属性:一组数据

类的方法:允许对进行操作的方法(行为)

比如:

类名:Tank 属性:重量 速度 材料 方法:开炮 移动 转弯

在类中定义方法的时候参数位置要写上self

执行 Cat() 在内存中申请了空间 返回对象的引用

而执行 tom = Cat() tom是创建的对象的引用

指向那个对象

添加属性

tom.name="xxx"  给tom添加属性name

tom.age=xx 给tom添加属性age

例子:

类Cat

tom=Cat()

tom.调用方法

tom.添加属性

class Cat:     #属性

    #方法     def eat(self):         print("猫在吃鱼....")

    def drink(self):         print("猫正在喝kele.....")

    def introduce(self):         #print("%s的年龄是:%d"%(tom.name, tom.age))         print("%s的年龄是:%d"%(self.name, self.age))

#创建一个对象 tom = Cat()

#调用tom指向的对象中的 方法 tom.eat() tom.drink()

#给tom指向的对象添加2个属性 tom.name = "汤姆" tom.age = 40

#获取属性的第1种方式 #print("%s的年龄是:%d"%(tom.name, tom.age))

tom.introduce()#相当于 tom.introduce(tom)

lanmao = Cat() lanmao.name = "蓝猫" lanmao.age = 10 lanmao.introduce()

self的作用: 你通过哪个对象去调用方法 self就指向哪个对象

tom.introduce() 相当于tom.introduce(tom)

而如果class中函数的形参不写入self 直接调用tom.introduce()

结果会显示多传入了一个参数 这个就是原因所在

还有 不一定要传入形参的时候传self a b c等任何数都行 只是我们约定俗成 用self

魔法方法1:__init__

方法:初始化对象 def __init__(self):             pass      初始化对象

创建对象的过程: 1.创建一个对象 2.python会自动的调用__init__方法 3.返回创建的对象的引用给tom

__init__也称为魔法方法

class Cat:     """定义了一个Cat类"""

    #初始化对象     def __init__(self, new_name, new_age):         self.name = new_name         self.age = new_age

    #方法     def eat(self):         print("猫在吃鱼....")

    def drink(self):         print("猫正在喝kele.....")

    def introduce(self):         print("%s的年龄是:%d"%(self.name, self.age))

#创建一个对象 tom = Cat("汤姆", 40) tom.eat() tom.drink() #tom.name = "汤姆" #tom.age = 40 tom.introduce()

lanmao = Cat("蓝猫", 10) #lanmao.name = "蓝猫" #lanmao.age = 10 lanmao.introduce()

1.创建对象 name = "汤姆" age = 40

2.调用__init__方法 3.返回这个对象的引用

1.创建对象 name = "蓝猫" age = 10 2.调用__init__方法 3.返回这个对象的引用

魔法方法2:__str__

用来获取对象描述信息

def __self__(self):      return xxx

print(tom)

打印出xxx(调用tom的信息)

class Cat:     """定义了一个Cat类"""

    #初始化对象     def __init__(self, new_name, new_age):         self.name = new_name         self.age = new_age

    def __str__(self):         return "%s的年龄是:%d"%(self.name, self.age)

    #方法     def eat(self):         print("猫在吃鱼....")

    def drink(self):         print("猫正在喝kele.....")

    def introduce(self):         print("%s的年龄是:%d"%(self.name, self.age))

#创建一个对象 tom = Cat("汤姆", 40)

lanmao = Cat("蓝猫", 10)

print(tom) print(lanmao)

打印结果为: 汤姆的年龄是40 蓝猫的年龄是10

通过全局变量 通过属性 来进行数据的共享

把函数的功能封装起来

def __test(self):         pass

这种方式是方法私有化

del不是真正删除了 而是删除了引用

def __del__(self):        pass

python解释器调用

class Dog:     def __del__(self):         print("-----英雄over------")

dog1 = Dog() dog2 = dog1

del dog1#不会调用 __del__方法,因为这个对象 还有其他的变量指向它,即 引用计算不是0 del dog2#此时会调用__del__方法,因为没有变量指向它了 print("====================")

#如果在程序结束时,有些对象还存在,那么python解释器会自动调用它们的__del__方法来完成清理工作

测量一个对象引用的计数方式:

使用sys模块中的getrefcount函数

import sys class T:       pass

t = T()

sys.getrefcount(t) >>2

tt = t sys.getrefcount(tt) >>3

del tt sys.getrefcount(t) >>2

父类/基类

继承

子类/派生类

我们定义了一个Animal类 父类/基类

下面有个Dog Cat的子类

Dog下面定义了一个wangcai的方法 tom的方法

wangcai只能使用Dog Animal类中的方法 tom只能使用Cat Animal类中的方法

不允许出现tom使用Dog中的方法 或者是wangcai使用Cat中的方法

重写 在子类中重写父类的方法

调用的时候只会调用子类的方法

super().bark()

super调用被重写的父类的方法

私有方法 私有的属性并不会被继承

如果调用的是继承的父类中的共有方法 可以在这个公有方法中访问父类中的私有属性和私有方法

但是如果在子类中实现了一个公有方法 那么这个方法是不能够调用继承的父类中的私有方法

class Base(object):        pass

class Base(object):     def test(self):         print("----Base")

class A(Base):     def test(self):         print("-----A")

class B(Base):     def test(self):         print("-----B")

class C(A,B):     pass     #def test(self):     #    print("-----C")

c = C() c.test()

print(C.__mro__)

类名.__mro__ 决定调用一个方法的时候 搜索的顺序 如果在某个类中找到了方法 那么就停止搜索

定义的时候对象不确定 调用的时候确定对象 这个方法叫多态

python既支持面向过程 也支持面向对象

python面向对象的三个基本要素是 封装 继承 多态

一个特殊的属性 能够知道这个对象的class

类在程序里面也是一个对象 称为类对象

由类创建出的对象为实例对象

实例对象的属性为实例属性 实例属性和对象有关系

类对象中的属性为类属性 类属性和类有关系

类属性是共享的

实例属性:和具体的某个实例对象有关系 并且 一个实例对象和另外一个实例对象是不共享属性的

类属性:类属性所属于类对象 并且多个实例对象之间共享同一个 类属性

class Tool(object):

    #类属性     num = 0

    #方法     def __init__(self, new_name):         #实例属性         self.name = new_name         #对类属性+=1         Tool.num += 1

tool1 = Tool("铁锹") tool2 = Tool("工兵铲") tool3 = Tool("水桶")

print(Tool.num)

实例方法 类方法 静态方法

class Game(object):

    #类属性     num = 0

    #实例方法     def __init__(self):         #实例属性         self.name = "laowang"

    #类方法     @classmethod     def add_num(cls):         cls.num = 100

    #静态方法     @staticmethod     def print_menu():         print("----------------------")         print("    穿越火线V11.1")         print(" 1. 开始游戏")         print(" 2. 结束游戏")         print("----------------------")

game = Game() #Game.add_num()#可以通过类的名字调用类方法 game.add_num()#还可以通过这个类创建出来的对象 去调用这个类方法 print(Game.num)

#Game.print_menu()#通过类 去调用静态方法 game.print_menu()#通过实例对象 去调用静态方法

@classmethod 装饰器 固定写法

通过一个类进行分离解耦

在父类中不去实现 在子类中实现

这就是工厂方法模式

def __new__(cls):     pass

当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径

class Dog(object):     def __init__(self):         print("----init方法-----")

    def __del__(self):         print("----del方法-----")

    def __str__(self):         print("----str方法-----")         return "对象的描述信息"

    def __new__(cls):#cls此时是Dog指向的那个类对象

        #print(id(cls))

        print("----new方法-----")         return object.__new__(cls)

#print(id(Dog))

xtq = Dog()

1.创建一个对象 2.调用__init__方法 3.返回对象的引用

而__new__方法就是重写父类的new方法

1.调用__new__方法来创建对象,然后找了个变量来接受__new__返回值,这个返回值表示 创建出来的对象的引用

2.__init__(刚刚创建出来的对象的引用) 初始化

3.返回对象的引用

而构造方法是既创建对象 又初始化 和__init__方法不等价

__new__只负责创建对象 __init__只负责初始化

class Dog(object):

    __instance = None

    def __new__(cls):         if cls.__instance == None:             cls.__instance = object.__new__(cls)             return cls.__instance         else:             #return 上一次创建的对象的引用             return cls.__instance

a = Dog() print(id(a)) b = Dog() print(id(b))

class Dog(object):

    __instance = None     __init_flag = False

    def __new__(cls, name):         if cls.__instance == None:             cls.__instance = object.__new__(cls)             return cls.__instance         else:             #return 上一次创建的对象的引用             return cls.__instance

    def __init__(self, name):         if Dog.__init_flag == False:             self.name = name             Dog.__init_flag = True

a = Dog("旺财") print(id(a)) print(a.name)

b = Dog("哮天犬") print(id(b)) print(b.name)

异常处理:

try:

except 出现异常的名字:

try:  print(num) except NameError:  print(111)

Exception

如果用了Exception,那么意味着只要上面的except没有捕获到异常 这个except一定会捕获到

Exception 不管产生什么异常 都会捕获到 就不需要去写许多异常了 异常方面很多

as 预处理方案 会给出产生该异常的原因

#coding=utf-8

try:     num = input("xxx:")     int(num)     #11/0     #open("xxx.txt")     #print(num)     print("-----1----")

except (NameError,FileNotFoundError):     print("如果捕获到异常后做的 处理....") except Exception as ret:     print("如果用了Exception,那么意味着只要上面的except没有捕获到异常,这个except一定会捕获到")     print(ret) else:     print("没有异常才会执行的功能") finally:     print("------finally-----")

print("-----2----")

Ctrl + C也是一个异常

自定义异常类

raise引发一个自定义的异常

log日志 会记录发生的异常

*.py文件就是模块

.pyc 字节码的后缀 翻译后的python代码

from 模块名 import 功能名1,功能名2,.....从模块中导入功能1,功能2,等等

from 模块名 import *  从模块中导入所有功能

这种方式缺陷:如果导入的模块的功能名相同 后面导入的会覆盖前面导入的

import msg msg.text1()

通过模块名.功能名调用

import time as tt 导入time模块 给它取个名字 叫tt tt.sleep(3)

不取和模块名相同的名字

import xxx

class ClassName(object):       def __init__(self,arg):               pass

def xxx():      pass

def main():     pass

if __name == '__main__':        main()

__all__ = ["功能名1","功能名2",...../或者类名也行]

定义的作用:放上将来你想要用的功能/类名,如果没放进去 调用import仍不能用

把模块有关联的放在一个文件夹中

在python2中调用文件夹名会直接失败 在python3中调用会成功,但是调用不能成功

解决办法是:

在该文件夹下加入空文件__init__.py python2会把该文件夹整体当成一个包

然后编辑__init__.py 

加入__all__ = ["功能名1","功能名2",...../或者类名也行]

再通过from 模块名 import * 通用写法是:from . import 模块名

这样就可以调用包中那些模块功能了

#如果导入这个模块的方式是 from 模块名 import * ,那么仅仅会导入__all__的列表中包含的名字

setup.py

from distutils.core import setup

setup(name="dongGe", version="1.0", description="dongGe's module", author="dongGe", py_modules=['TestMsg.sendmsg', 'TestMsg.recvmsg'])

模块的发布过程: 1.创建文件setup.py 传入模块.功能 2.python3 setup.py build 3.python3 setup.py dist 4.生成压缩包,然后可以发布到github.com上

系统安装包 sudo python3 setup.py install

python2中range(10)返回值是一个列表[0,...,9] 而在python3中返回值是range(0,10)

range(0,10)在python2中返回是一个列表[0,...,9] 而在python3中返回值是range(0,10)

range有风险 如果将来你需要一个很大的值 因为需要占用很大的空间 所以不给你

如果python3中想要返回值是一个列表

使用a = [i for i in range(1,18)] 这样可以返回一个列表

在python2中这种写法也适合

(参数1,参数2,参数3,.....) for 参数1 in range(第1个数) for 参数2 in range(第2个数) 。。。。。。。

set 字典

list 列表

while True: 1.检测事件,如果有时间就控制相应的图片移动 2.把所有的图片重新画一遍

1/60s --> 动画效果

列表循环删除的时候不能删除循环的那个列表 我们可以申请一个新的列表去存