Python基础学习笔记

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 --> 动画效果

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

以上是 Python基础学习笔记 的全部内容, 来源链接: utcz.com/z/388488.html

回到顶部