Python学习笔记 之 从入门到放弃

笔记目录

9月22日:《基础教程》基础知识

第1章 快速改造:基础知识

  • 长整数,python2和python3有关长整数的区别?

python2中有long类型
python3中没有long类型,只有int类型

>>> 1000000000000000000    #教材
1000000000000000000L
>>> 1000000000000000000L
1000000000000000000L
>>> 1000000000000000000    #测试
1000000000000000000
>>> 1000000000000000000L
SyntaxError: invalid syntax
  • 十六进制和八进制
>>> 0xAF    #十六进制数前面是0x
175
>>> 010    #八进制数前面是0
8

·模块导入

  • 除非真的需要from这个形式的模块导入语句,否则应该坚持使用普通的import。
>>> import math    #正常导入模块,使用导入模块中的函数
>>> math.floor(32.9)
32
--------------------
>>> from math import sqrt    #使用from可以直接使用函数不用加模块,但是会有不同模块重名函数的现象需要注意
>>> sqrt(9)
3.0

·用变量引用函数(或者Python中大多数的对象)

>>> foo=math.sqrt
>>> foo(4)
2.0

·将数值转换成字符串的方法:str类型、repr函数

  • 将数值转换成字符串的方法:str类型、repr函数和 反引号(反引号在python 3中已经不再使用)
>>> temp=23
>>> print("The temperature is "+ repr(temp))
The temperature is 23

9月23日:列表、元组

第2章 列表和元组
2.1序列概览

  • 序列(内建序列):列表、元组、字符串、buffer对象、xrange对象

·序列索引可以为负数:

索引范围为[ (-n) ~ (n-1) ]

sequence = [1,2,3,4,5]
print("sequence[4] = " + str(sequence[4]))
print("sequence[-5] = " + str(sequence[-5]))

sequence[4] = 5
sequence[-5] = 1

·序列的分片和步长

  • 冒号“:”实现分片 和 步长,步长隐式设置为1
  • 形式为:number[ a : b [ : c ] ]
  • c不能为0,默认为;a为分片的首个元素索引,b为分片最后一个元素的下一个元素索引,也就是a在分片中,b不在分片中
  • 从首个元素开始取时可以空置a,取到最后一个元素时可以空置b
  • 如果c是正数(比如隐式设置),那么number[a]必须在number[b]左边;如果c是负数,那么number[a]必须在number[b]右边。
number = [1,2,3,4,5,6,7,8,9,10]
print("number[2:10] = " + str(number[2:10]))			#冒号“:”实现分片,步长隐式设置为1
print("number[2:10:2] = " + str(number[2:10:2]))		#冒号“:”实现分片 和 步长,步长隐设置为2
print("number[:8] = " + str(number[:8]))				#从首个元素开始,a为0,也可以空置
print("number[2:] = " + str(number[2:]))				#d到最后一个元素结束,b为n,也可以空置
print("number[10:0:-2] = " + str(number[10:0:-2]))		#步长为负数,a索引元素必须在b索引元素右边
print("number[::2] = " + str(number[::2]))				#a,b都空置
print("number[::] = " + str(number[::]))				#a,b,c都空置

number[2:10] = [3, 4, 5, 6, 7, 8, 9, 10]
number[2:10:2] = [3, 5, 7, 9]
number[:8] = [1, 2, 3, 4, 5, 6, 7, 8]
number[2:] = [3, 4, 5, 6, 7, 8, 9, 10]
number[10:0:-2] = [10, 8, 6, 4, 2]
number[::2] = [1, 3, 5, 7, 9]
number[::] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

·序列相加,乘法;列表和字符串不能相加

number1 = [1,2,3]
number2 = [4,5,6]
string1 = "Hello,"
string2 = "World!"
print("number1 + number2 =" + str(number1 + number2))	#列表相加
print("string1 + string2 =" + string1 + string2)
#print("number1 + string1 =" + str(number1 + string1))
#这句报错,列表和字符串不能相加
print("number1 * 3 = " + str(number1 * 3))				#列表相乘

number1 + number2 =[1, 2, 3, 4, 5, 6]
string1 + string2 =Hello,World!
number1 * 3 = [1, 2, 3, 1, 2, 3, 1, 2, 3]

·in运算符 测试成员资格

subject = "$$$ Get rich now!!! $$$"
if "$$$" in subject : print("'$$$' in subject\n")

'$$$' in subject

9月24日:序列分片,列表方法,字符串格式化

2.3 列表:Python的苦力

·list函数:将 所有类型的序列 转换成 列表

  • 字符串不能修改,可以用list函数转化成列表
temp = list("Hello!")
print(temp)

['H', 'e', 'l', 'l', 'o', '!']

·删除列表元素 del

  • 使用del语句实现,也可以删除分片
names = ['Alice','Beth','Cecil','Dee-Dee','Earl']
print(names)
del names[2]
print(names)
del names[1:3]
print(names)

['Alice', 'Beth', 'Cecil', 'Dee-Dee', 'Earl']
['Alice', 'Beth', 'Dee-Dee', 'Earl']
['Alice', 'Earl']

·分片赋值 name[a:b]

  • 可以通过 分片 进行多个元素赋值;
  • 也可以与原序列不等长的赋值;
  • 还可以通过 分片赋值 插入或者删除元素;
name = list('Perl')	
name[2:] = list('ar')		#通过分片进行多个元素赋值
print(name)
name[1:] = list('ython')	#与原序列不等长的赋值
print(name)
name[1:1] = list('&&&&&&&')	#通过 分片赋值 插入新的元素
print(name)
name[1:12] = []				#通过 分片赋值 删除元素
print(name)

['P', 'e', 'a', 'r']
['P', 'y', 't', 'h', 'o', 'n']
['P', '&', '&', '&', '&', '&', '&', '&', 'y', 't', 'h', 'o', 'n']
['P', 'n']

·列表方法

  • 列表方法:append,count,extend,index,insert,pop,remove,reverse,sort

·列表方法作用和返回值 表格

列表方法作用返回值相关内容
append列表末尾追加元素None
count元素出现次数次数
extend列表末尾扩展另一个序列None末尾分片赋值
index第一个匹配值的索引索引
insert列表插入元素None分片赋值
pop移除最后一个元素元素insert(0,…),pop(0),
append(),pop()
remove移除匹配项的第一个元素None
reverse列表反向Nonereversed ( ) 函数返回迭代器
可以使用 y = list(reversed(x))
sort列表排序Nonesorted ( ) 函数返回列表
可以使用 y = sorted(x)

·高级排序,sort方法的使用

  • number.sort(cmp,key=None,reverse=False)
  • sort方法三个参数,第一个cmp函数;
  • 第二个key关键字参数,排序过程中使用的函数,如len;
  • 第三个reverse,布尔值,默认设置为False不反向;
  • 以上三个参数适用于sorted()函数;

·元组:不可变序列

  • 一个元素的元组,必须加逗号,否则即使加圆括号也不行;
print(3*(42))
print(3*(42,))

126
(42, 42, 42)
  • tuple函数,把一个序列转换为元组;
    类似于list函数,把一个序列转换为列表;

  • 元组意义:

1、元组可以作为映射的键使用;
2、元组一般作为内建函数和方法的返回值;

第3章 使用字符串

·字符串格式化 %

  • 下面例子中values如果是序列,会被解释成一个值;
  • 如果本身就有%,那么必须使用%%,%才不会被认为是 转换说明符;
string1 = "Hello,%s! %s enough fo ya?"
values = ("world","Hot")	#values如果是序列,会被解释成一个值
print(string1 %values)

Hello,world! Hot enough fo ya?

#对比
string1 = "Hello,%s! enough fo ya?"
values = ["world","Hot"]	#values如果是序列,会被解释成一个值
print(string1 %values)

Hello,['world', 'Hot']! enough fo ya?
string1 = "Pi with three decimals: %.3f."
from math import pi
print(string1 % pi)

Pi with three decimals: 3.142. 

·字符串格式化转换说明符

  • 注意 顺序
内容说明
1%字符标记转换说明符的开始
2转换标志
(可选)
- 表示左对齐;
+ 表示在转换值之前要加上正负号;
“ ”(空白字符)表示正数之前保留空格;
0 表示转换值若位数不够则用0填充
3最小字段宽度
(可选)
转换后的字符串至少应该具有该值指定的宽度。
如果是 * ,则宽度会从值元组中读出
4点( . )后跟精度值
(可选)
如果转换的是实数,精度值就表示出现在小数点后的位数。
如果转换的是字符串,那么该数字就表示 最大字段宽度。
如果是 * ,那么精度将会从元组中读出。
5转换类型下表
转换类型含义
d,i带符号的十进制整数
o不带符号的八进制
u不带符号的十进制
x不带符号的十六进制(小写)
X不带符号的十六进制(大写)
e科学计数法表示的浮点数(小写)
E科学计数法表示的浮点数(大写)
f,F十进制浮点数
g如果指数大于-4或者小于精度值则和e相同,其他情况与f相同
G如果指数大于-4或者小于精度值则和E相同,其他情况与F相同
C单字符(接受整数 或者 单字符字符串)
r字符串(使用 repr 转换任意Python对象)
s字符串(使用 str 转换任意Python对象)
from math import pi
print("%10f" % pi)					#字段宽度 10
print("%10.2f" % pi)				#字段宽度 10,精度 2
print("%*.*s" % (10,5,"abcdefgh"))	#使用 * 作为字段宽度或者精度(或者两者都使用*),数值会从元组参数中读出

  3.141593
      3.14
     abcde
from math import pi
print("%010.2f" % pi)					#字段宽度 10,精度 2,位数不够用 0 填充
print("%-10.2f" % pi + "abcd")				#字段宽度 10,精度 2,- 表示左对齐数值,打印出来的数字右侧有额外的空格
print("% 5d" % 10 + "\n" + "% 5d" % -10)	#" "意味着在正数前面加上空格,
print("%+5d" % 10 + "\n" + "%+5d" % -10)	# + 表示不管是正数负数都标示出符号

0000003.14
3.14      abcd
   10
  -10
  +10
  -10

·字符串 常用方法

string1.find(string2[,a[,b]])字符串string1起始a和终止b范围内查找字符串string2,并返回最左端索引值,没找到返回-1,
可以不提供a,b;也可以只提供 a 起始
string1.join(string2)返回用string1连接string2中元素的字符串
string1.split([separate[,maxsplit]])返回字符串string1中用字符串separate分隔所得的所有 单词的列表,maxsplit指定最多切割几次;
separate默认设置空格“ ”,maxsplit默认设置无穷大
string.lower()返回字符串string的小写字母版本
string1.replace(old,new[,max]]返回字符串string1的副本,用new字符串替换old字符串,最多替换max次
string1.strip([chars])返回字符串string1的副本,其中string1开头和结尾所有的位于字符列表[chars]中的字符都被去除;
[chars]隐形设置为所有的空白字符,如空格、tab和换行符
string.translate(table[,deletechars])返回字符串的副本,其中所以字符都是用table进行了转换,可选择删除出现在deletechars中的所有字符;
table由string模块中的maketrans函数构造
table = str.maketrans("cs","kz")		#注意python 3 中maketrans的使用方式
string1 = "this is an incredible test"
string2 = string1.translate(table)
print(string1 + '\n' + string2 + '\n')

this is an incredible test
thiz iz an inkredible tezt

9月25日:字典方法,python基本语句

·字典基本操作

  • dict函数建立字典,类似list、tuple、str一样;
    dict可以通过其他字典 或者 (键-值)对的序列建立字典;
    也可以通过关键字参数创建字典;
  • 字典 是唯一内建的映射类型;
  • len(d);del d[k];k in d;等操作都可用,只不过k in d 查找的是键的成员资格,而不是值得成员资格;
items = [('name','Gumby'),('age',42)]
d = dict(items)							#通过其他字典 或者 (键-值)对的序列建立字典;
print(d)
d2 = dict(number = 54,name = 'Richard')	#通过关键字参数创建字典;
print(d2)

{'name': 'Gumby', 'age': 42}
{'number': 54, 'name': 'Richard'}

·字典的格式化字符串

  • 字典除了可以元组一样使用字符串格式化功能,还可以在每个转换说明符中的 % 字符后面,加上(键),后面再跟其他元素说明;
items = [('name','Gumby'),('age',42)]
d = dict(items)							#通过其他字典 或者 (键-值)对的序列建立字典;
print("%(name)s's age is %(age)d!" %d)	#在每个转换说明符中的 % 字符后面,加上(键),后面再跟其他元素说明

Gumby's age is 42!

·字典方法

字典方法作用返回值相关
d.clear()清除字典中所有的项None
d.copy()浅复制一个拥有相同键-值对的新字典,一般用deepcopy函数进行深复制dictdeepcopy(dict)
dict.fromkeys(sequence[,value])返回从sequence中获得的键和被设置为value的值(value的默认设置值None)的字典。可以直接在字典类型dict上作为类方法调用dict
d.get(key[,default])如果d[key]存在,那么将其返回;否则返回给定的默认值default(default不设置默认None)d[key]或default
d.items()返回字典d中(键,值)对的列表list
d.iteritems()和d.items()相同,只不过返回的是迭代器,是列表中的一个可迭代对象iterator
d.keys()返回字典d的键的列表list
d.iterkeys()和d.keys()相同,只不过返回的是迭代器,是列表中的一个可迭代对象iterator
d.values()返回字典d的值得列表list
d.itervalues()和d.values()相同,只不过返回的是迭代器,是列表中的一个可迭代对象iterator
d.pop(key[,default])移除,并且返回d[key],如果d[key]不存在则返回default
d.popitem()移除,并返回字典d中任意一个(键-值)对tuple(键,值)
d.setdefault(key[,default])返回d[key];d[key]不存在返回给定的默认值default(默认为None)并将d[key]的值绑定给defaultd[key]或default
d.update(other)other如果是字典,会将other每一项都加入d中(可能会改写已存在项);other也可以是(键-值)对的序列或关键字参数,update方法和dict函数一样使用None

·python基本语句

  • print语句用(,)逗号间隔参数,打印的结果每个逗号都有一个空格;
  • import语句可以加as用于别名,也可以结合 from * import * as *;

·赋值语句

  • 序列解包:
    -多个赋值操作可以同时进行,也可以交换多个变量,还可以结合(*)星号运算符;
x,y,z = 1,2,3				#多个赋值操作可以同时进行
print(x,y,z)
x,y = y,x					#也可以交换多个变量
print(x,y,z)
x,y,*rest,z = 1,2,3,4,5		#还可以结合(*)星号运算符
print(x,y,rest,z)


1 2 3
2 1 3
1 2 [3, 4] 5
  • 链式赋值:x = y = somefunction()
  • 增量赋值:+=;-=;*=;/=;%=;

·条件语句

  • 布尔值为假:False,0;None,(),"";[];{};
  • if / elif / else
  • 比较运算符 连接使用 :0 < age < 100;
  • is:同一性运算符:判定 同一性 而不是 相等性;
  • and、or、not:布尔运算符
  • a if b else c
print("abc" if True else "ABC")				# a if b else c
print("abc" if False else "ABC")

abc
ABC
  • 断言:assert
age = -1
assert 0<age<100 "The age must be realistic!"
print(age)

assert 0<age<100 "The age must be realistic!"                     ^
SyntaxError: invalid syntax

·循环语句

  • range()函数 和 xrange()函数:内建的范围函数
    ·range()函数以此创建整个序列,而xrange()函数一次只创建一个数,效率更高
    ·注意:python3 中取消了 range 函数,而把 xrange 函数重命名为 range,所以现在直接用 range 函数即可
for number in range(1,101,20):		#range([start,] end [,step])
	print(number)

1
21
41
61
81
  • 并行迭代:zip()函数
    ·zip()函数:可以把两个序列“压缩”在一起,然后返回一个元组的列表;
    ·zip可以处理不等长的序列,当最短的序列“用完”为止;
names = ['anne','beth','george','damon']
ages = [12,45,109]
for name,age in zip(names,ages):			#把两个序列“压缩”在一起,然后返回一个元组的列表
	print(name,'is',age,'years old')		#names有四个元素,ages有三个元素,zip可以处理不等长的序列,当最短的序列“用完”为止;

anne is 12 years old
beth is 45 years old
george is 109 years old
  • 内建的enumerate()函数:可以在提供索引的地方迭代 索引-值 对;
names = ['anne','beth','george','damon']
for index,name in enumerate(names):			
	print(index,name)		

0 anne
1 beth
2 george
3 damon
  • while True / break习语

·while True实现一个永远不会停止的循环,但是在循环内部的if语句用break语句跳出

while True:
	word = input("Please enter a word:")
	if not word:
		break
	print ('The word was ' + word)

Please enter a word:Richard
The word was Richard

·列表推导式——轻量级循环

abc = [x*x for x in range(10)]						#列表推导式:工作方式类似于for循环
print(abc)
abc = [x*x for x in range(10) if x%3==0]			#可以通过增加一个if部分添加到列表推导式中
print(abc)
abc = [(x,y) for x in range(3) for y in range(3)]	#也可以增加更多for语句的部分
print(abc)
abc = [(x,y) for x in range(3) for y in range(3) if x<y]	
print(abc)

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 9, 36, 81]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
[(0, 1), (0, 2), (1, 2)]

·其他语句:pass、del、exec和eval

  • pass语句:python中控代码块是非法的,解决方法就是在语句块中加上一个pass语句;
names = ['Richard','Tom','Jerry']
for name in names:
	if name == 'Richard':
		print('Welcome!')
	elif name == 'Tom':
		pass						#不允许有空代码块
	elif name == 'Jerry':
		print('Access Denied!')

Welcome!
Access Denied!
  • del语句:不仅会移除一个对象的引用,也会移除那个名字本身;
  • exec执行字符串;eval求值字符串;命名空间:in scope;

9月26日:

·直接赋值,浅拷贝copy、深拷贝deepcopy

  • 直接赋值:传递对象的引用而已,原始列表改变,被赋值的也会做相同的改变
    ·列表list、字典dict都是如此;
    ·对象拷贝的是引用
xo=[1,2,3,4,5]
yo=xo			#列表list直接赋值
yo[1]=200
print(xo)
print(yo)

[1, 200, 3, 4, 5]
[1, 200, 3, 4, 5]
  • 浅拷贝copy:没有拷贝子对象,所以原始数据改变,子对象会改变
    ·对象拷贝的是数据
    ·子对象拷贝的是引用
import copy
xo=[1,2,3,[4,5,'a'],6]
yo=copy.copy(xo)		#浅拷贝
yo.append(7)			#结果原始对象没有改变,因为原始对象拷贝的是原始数据
print(xo)
print(yo)
xo=[1,2,3,[4,5,'a'],6]
yo=copy.copy(xo)		#浅拷贝
yo[3].append('b')		#结果子对象改变了,因为子对象拷贝的是引用
print(xo)
print(yo)

[1, 2, 3, [4, 5, 'a'], 6]			#结果原始对象没有改变,因为原始对象拷贝的是原始数据
[1, 2, 3, [4, 5, 'a'], 6, 7]
[1, 2, 3, [4, 5, 'a', 'b'], 6]		#结果子对象改变了,因为子对象拷贝的是引用
[1, 2, 3, [4, 5, 'a', 'b'], 6]
  • 深拷贝deepcopy:包含对象里面的子对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变
    ·对象拷贝的是数据
    ·子对象拷贝也是数据
import copy
xo=[1,2,3,[4,5,'a'],6]
yo=copy.deepcopy(xo)		#深拷贝
yo.append(7)				#结果原始对象没有改变,因为原始对象拷贝的是原始数据
print(xo)
print(yo)
xo=[1,2,3,[4,5,'a'],6]
yo=copy.deepcopy(xo)		#深拷贝
yo[3].append('b')			#结果子对象也没有改变,因为子对象拷贝的是也是原始数据
print(xo)
print(yo)

[1, 2, 3, [4, 5, 'a'], 6]			#结果原始对象没有改变,因为原始对象拷贝的是原始数据
[1, 2, 3, [4, 5, 'a'], 6, 7]
[1, 2, 3, [4, 5, 'a', 'b'], 6]		#结果子对象也没有改变,因为子对象拷贝的是也是原始数据
[1, 2, 3, [4, 5, 'a', 'b'], 6]

·函数

  • 使用 def 语句创建函数

·文档化函数

  • 可以加入注释(#开头)
  • 在 def 语句后面,函数的开头写下字符串,他就会作为函数的一部分进行存储,成为 文档字符串
  • 可以用 hanshuming.__doc__进行访问(注意这里前后都是双下划綫)
def square(x):
	'Calculates the square of the number x.'
	return x*x
print(square.__doc__)

Calculates the square of the number x.

·位置参数、关键词参数、提供默认值

  • 位置参数:用 参数的顺序 作为区分参数的依据
  • 关键词参数:指定 每个关键词 的参数,关键词要相同,顺序可以不同
  • 提供默认值:函数定义的时候,直接将关键词赋值,这样调用函数的时候可以不提供这些参数的值,而是用定义时候的默认值
def hello_1(greeting,name):										#位置参数,按照参数顺序进行传参
	print('%s,%s!' %(greeting,name))
hello_1('Hello','world')

hello_1(name = 'all the people',greeting = 'Nice to meet you')	#关键词参数,按照关键词进行传参,无关顺序

def hello_2(greeting = 'Hello',name = 'World'):					#greeting参数没有提供,使用了默认值,name没有
	print('%s,%s!' %(greeting,name))	
hello_2(name = 'Richard')

Hello,world!
Nice to meet you,all the people!
Hello,Richard!

·收集参数:定义函数时允许使用不定数目的参数

  • 用星号(*)将剩下的 位置参数 收集到一个元组中
  • 用双星号(**)将剩下的 关键字参数 收集到一个字典中
def print_param(x,y,z=3,*pospar,**keypar):
# x,y,z三个参数有默认值	
# *pospar将剩下的 位置参数 收集到一个元组中
# **keypar将剩下的 关键字参数 收集到一个字典中
	print(x,y,z)
	print(pospar)
	print(keypar)
print_param(1,2,3,4,5,6,7,foo=1,bar=2)

1 2 3
(4, 5, 6, 7)
{'foo': 1, 'bar': 2}

·收集参数逆过程:调用函数时“分割”字典或者序列

  • 用星号(*)在调用函数时“分割”序列
  • 用双星号(*)在调用函数时“分割”字典
def add(x,y):
	print('x + y = ' + str(x+y)) 
params = (1,2)
add(*params)										#用星号(*)在调用函数时“分割”序列

def hello(greeting,name):
	print('%s,%s!' %(greeting,name))
params2 = {'greeting': 'Hello', 'name': 'world'}
hello(**params2)									#用双星号(*)在调用函数时“分割”字典

x + y = 3
Hello,world!

·全局变量与局部变量

  • 在子函数中,使用globals()[“ 全局变量名 ”]使用全局变量
  • locals()函数和globals()函数使用相同,会返回局部变量值

  • 在子函数中,想要声明全局变量,可以使用 global 关键词
  • 在子函数中,想要声明外部作用域变量,如上一层函数的局部变量,可以使用 nonlocal 关键词

9月28日:抽象、异常

·多态、封装、继承

多态:可以对不同类的对象使用同样的操作;不需要检测类型
封装:对外部世界隐藏对象的工作细节;
继承:以通用的类为基础建立专门的类对象;

  • 唯一能毁掉多态的是,使用函数显式的检查类型,比如type、isinstance、issubclass等,要避免使用这些;
  • 方法(method)和特性(attribute)是构成对象(object)的一部分;

·类和类型

  • 旧版本中,类和类型区别明显,内建的对象基于类型,自定义的对象基于类,可以创建类不能创建类型;新版本中可以创建内建类型的子类型,类和类型区别不大;
  • 描述对象的类:习惯使用单数名词,首字母大写,如Bird、Lark;
  • 定义子类只是个定义更多(或者是重载已经存在的)的方法的过程;

·特性、函数和方法

  • self参数:定义方法时对于对象自身的引用;
  • 可以将特性绑定到一个普通函数上,也可以使用其他变量引用同一个方法:
class Bird:
	song = 'Squaawk!'
	def sing(self):
		print(self.song)
	def method(self):
		print('I have a self!')
def function():
	print('I don\'t ...')

instance = Bird()
instance.method()
instance.method = function		#将特性绑定到一个普通函数上
instance.method()

bird = Bird()
bird.sing()
birdsong = bird.sing			#使用其他变量引用同一个方法
birdsong()

I have a self!
I don't ...
Squaawk!
Squaawk!

·私有

  • python并不直接支持私有方式,为了让方法或者特性变为私有(从外部无法访问),只要在它的名字前面加上 双下划线 。
class Secretive:
	def __inaccessible(self):
		print("Bet you can\'t see me...")
	def accessible(self):
		print("The secret message is:")
		self.__inaccessible()
s = Secretive()
s.accessible()							#没加双下划綫的方法或特性可以被外部访问
try:
	s.__inaccessible()						#加双下划线的方法或特性不能被外部访问
except AttributeError as e:
	print(e)

The secret message is:
Bet you can't see me...
'Secretive' object has no attribute '__inaccessible'
  • 类的内部定义中,所有以双下划线开始的名字,都被“翻译”成前面加上单下划线和类名的形式:
print(Secretive._Secretive__inaccessible)

<function Secretive.__inaccessible at 0x02E540B8>
  • 所以基于上面的“解释”,还是可以在类外访问这些私有方法,尽管不应该这么做:
s._Secretive__inaccessible()

Bet you can't see me...
  • 如果不需要使用这种方法但是又想让其他对象不要访问内部数据,可以使用 单下划线 进行习惯说明;比如所有前面有下划线的名字都不会被带星号的import语句导入from module import *

·类的命名空间

  • 类的定义就是执行代码块,所以定义类时会生成这个类的命名空间,这个命名空间可以由 类内的所有成员 访问;
class C:
	members = 0
	def init(self):
		C.members += 1
x = C()
x.init()
print(C.members)
y = C()
y.init()				#members特性是C类的所有实例共同的,而不是每个实例都有一个
print(C.members)

1
2

·超类、检查继承,多类继承

  • 定义类时在括号里指定超类(基类);
  • 使用内建函数issubclass函数检查一个类是不是另一个的子类;
  • 想要知道已知类的基类们,可以直接使用类的特殊特性__bases__;
  • 检查一个对象是否是一个类的实例,可以使用isinstance函数;
  • 想知道一个对象属于哪个类,可以使用__class__特性;
  • 多类继承时,写在前面的先继承的超类会重写后面超类的同名方法;多类继承要避免使用;
  • 查看对象内存储的值,可以使用__dict__特性;
class C:
	def method(self):
		print('This is a superclass C!')
class D:
	def method(self):
		print('This is a superclass D!')
class SubCD(C,D):
	members = 0
	def submethod(self):
		self.id = 0
		print('This is a subclass SubCD!')
print(issubclass(D,C),issubclass(SubCD,C))			#使用内建函数issubclass函数检查一个类是不是另一个的子类;
print(SubCD.__bases__)								#想要知道已知类的基类们,可以直接使用类的特殊特性__bases__;
subcd = SubCD()
print(isinstance(subcd,SubCD),isinstance(subcd,C))	#检查一个对象是否是一个类的实例,可以使用isinstance函数;
print(subcd.__class__)
subcd.submethod()
subcd.method()					#多类继承,写在前面的先继承的超类会重写后面超类的同名方法,这里method是C的而不是D的
print(subcd.__dict__)								#查看对象内存储的值
		
		
False True
(<class '__main__.C'>, <class '__main__.D'>)
True True
<class '__main__.SubCD'>
This is a subclass SubCD!
This is a superclass C!
{'id': 0}

·异常

  • 异常基类:Exception,内建异常都在exceptions模块中;

  • raise可以引发异常,不用参数(except子句内重引发当前捕捉到的异常),也可以 raise IndexError('index out of bounds')

  • except子句:except (ZeroDivisionError,TypeError) as e:注意必须有圆括号

  • try / except / except / else / finally语句:
    except子句,捕捉到异常以后做什么
    else子句,没有捕捉到异常做什么
    finally子句,不管捕捉到还是没捕捉到,做完finally子句中的事再结束,一半用于关闭文件或者网络套接字

  • 栈跟踪:如果异常在函数内引发而没有被捕捉处理,它会“浮”到函数调用的地方,还没有被处理的话则会一直传播到主程序,如果主程序没有异常处理程序,程序会带着 栈跟踪 中止。

10月5日:

·魔法方法、属性和迭代器

·新式类

  • 使用新式方法:__metaclass__ = type
  • 如果没有兼容之前旧版本Python的需要,那么所有的类都写为新式的类,并且使用super函数这样的特性;

·构造方法

  • 自己写构造方法:def __init__(self)
  • 析构方法:__del__(self),因为调用的具体时间是不可知的,所以要尽力避免使用__del__函数;
  • 子类的构造方法必须调用超类的构造方法来确保进行基本的初始化,方法:(1)调用超类构造方法的未绑定版本;(2)使用super函数。
class Bird:
	def __init__(self):
		self.hungry = True
	def eat(self):
		if self.hungry:
			print("Aaaah...")
			self.hungry = False
		else:
			print("No,Thanks!")
class SongBird(Bird):
	def __init__(self):
		Bird.__init__(self)					#旧版本Python使用的是旧式类,需要调用超类构造方法的未绑定版本
		super(SongBird,self).__init__()		#新式类 使用super函数
		self.sound = "Squawk!"
	def sing(self):
		print(self.sound)
sb = SongBird()
sb.sing()
sb.eat()
sb.eat()

Squawk!
Aaaah...
No,Thanks!

(1)在调用一个实例的方法时,该方法的self参数会被自动绑定到实例上(这成为绑定方法)。但如果直接调用类的方法(比如Bird.__init__),那么就没有实例会被绑定,这样就可以自由地提供需要的self参数,这样的方法成为未绑定方法。
(2)当前的类和对象可以作为super函数的参数使用,调用函数返回的对象的任何方法都是调用超类的方法,而不是当前类的方法。super函数会查找所有的超类(以及超类的超类),知道找到所需的特性为止(或者引发一个AttributeError异常)

·魔法方法创建序列和映射、子类化列表字典字符串

·属性

# 定义一个类
class A(object):
 
    # 类属性,直接在类中定义的属性是类属性
    #   类属性可以通过类或类的实例访问到
    count = 0
 
    def __init__(self):
        # 实例属性,通过实例对象添加的属性属于实例属性
        #   实例属性只能通过实例对象来访问和修改,类对象无法访问修改
        self.name = '孙悟空'
        self.count += 1				#这里self.count和A.count是不同的,A.count是类属性,self.count是实例属性
 
    # 实例方法
    #   在类中定义,以self为第一个参数的方法都是实例方法
    #   实例方法在调用时,Python会将调用对象作为self传入  
    #   实例方法可以通过实例和类去调用
    #       当通过实例调用时,会自动将当前调用对象作为self传入
    #       当通过类调用时,不会自动传递self,此时我们必须手动传递self
    def test(self):
        print('这是test方法~~~ ' , self)    
 
    # 类方法    
    # 在类内部使用 @classmethod 来修饰的方法属于类方法
    # 类方法的第一个参数是cls,也会被自动传递,cls就是当前的类对象
    #   类方法和实例方法的区别,实例方法的第一个参数是self,而类方法的第一个参数是cls
    #   类方法可以通过类去调用,也可以通过实例调用,没有区别
    @classmethod
    def test_2(cls):
        print('这是test_2方法,他是一个类方法~~~ ',cls)
        print(cls.count)
 
    # 静态方法
    # 在类中使用 @staticmethod 来修饰的方法属于静态方法  
    # 静态方法不需要指定任何的默认参数,静态方法可以通过类和实例去调用  
    # 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数
    # 静态方法一般都是一些工具方法,和当前类无关
    @staticmethod
    def test_3():
        print('test_3执行了~~~')
 
 
a = A()
#a.count = 10
#A.count = 100
#print('A ,',A.count) 
#print('a ,',a.count) 
#print('A ,',A.name) 
#print('a ,',a.name)   
 
# a.test() 等价于 A.test(a)
 
# A.test_2() 等价于 a.test_2()
 
A.test_3()
a.test_3()

·迭代器

  • 只要实现了__iter__方法的对象都能进行迭代,不止序列和字典;
  • __iter__方法会返回一个迭代器,所谓的迭代器就是具有next方法。Python 3.0迭代器对象实现__next__方法而不是next方法,新的内建函数next()可以用于访问这个方法,也就是next(it)等同于以前的it.next()
  • 可以用list构造方法显式地将迭代器转化成列表
class TestIterator:					#TestIterator是一个迭代器
	value = 0
	def __next__(self):				#使用next函数会出错误,必须使用__next__函数
		self.value += 1
		if self.value > 10:
			raise StopIteration
		return self.value
	def __iter__(self):
		return self					#返回自身
		
ti1 = TestIterator()
for v in ti1:
	if v>5 :
		print(v)
		break

ti2 = TestIterator()	
li = list(ti2)						#使用list构造方法显式地将迭代器ti2转化成列表
print(li)

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
6

·生成器

  • 生成器是一种用普通的函数语法定义的迭代器,是一个饱含yield关键字的函数;就算不使用生成器也是也可以的,但是生成器更优雅;
def flatten(nested):				#生成器就是带有关键字yield的函数
	for sublist in nested:
		for element in sublist:
			yield element			#yield关键字
nested = [[1,2],[3,4],[5]]
for num in flatten(nested):
	print(num)
li = list(flatten(nested))
print(li)

1
2
3
4
5
[1, 2, 3, 4, 5]
  • 递归的生成器处理多层嵌套
  • 不能迭代类似于字符串的对象,一是字符串不应该被展开而应该作为一个原子值,二是字符串强行被展开的时候会导致无穷递归,因为一个字符串的第一个元素是另一个长度为1的字符串,而长度为1的字符串的第一个元素就是字符串本身。
  • 检查一个对象是不是类似于字符串最简单、最快速的方法:试着将对象和一个字符串拼接,看会不会出现TypeError。不是用isinstance函数检查类型是不是字符串,而是检查对象的行为是不是像一个字符串。
def flatten(nested):				
	try:
		#不要迭代类似于字符串的对象,
		try:
			nested + ' '
		except TypeError:
			pass
		else:
			raise TypeError			#而是把字符串当成一个整体原子值

		for sublist in nested:
			for element in flatten(sublist):		#这利用了递归处理嵌套多层的列表
				yield element
	except TypeError:
		yield nested

nested = [[1,2,[3,[4]]],[[5,6],7],[8],'qwe',[9,["asd",10]]]	#有多层嵌套列表,列表中也有字符串,
li = list(flatten(nested))
print(li)

[1, 2, 3, 4, 5, 6, 7, 8, 'qwe', 9, 'asd', 10]
  • yield是一个表达式,而不是语句使用,也就是说yield方法返回值,返回的是外部通过send方法发送的值;
  • 生成器在旧版本中没有,可以用列表和append方法进行模拟

·八皇后问题

  • 这里用生成器解决八皇后问题还需要继续理解一下,特别是相比return
def conflict(state,nextX):
	nextY = len(state)
	for i in range(nextY):
		if (state[i]==nextX)or((i-state[i])==(nextY-nextX))or((i+state[i])==(nextY+nextX)):
		#if abs(state[i]-nextX) in (0,nextY-i):  #两个点的横坐标差 等于 纵坐标差
			return True 
	return False
def queen(num=4,state=()):
	for pos in range(num):
		if not conflict(state,pos):
			if len(state)==num-1:
				yield (pos,)
			else:
				for result in queen(num,state+(pos,)):
						yield (pos,)+result
li=list(queen(4))
print(li)

[(1, 3, 0, 2), (2, 0, 3, 1)]

附录A:到时待办

  • 下载使用Sublime Text 3,用来编写Python代码;
  • 下载使用Visual Studio Code,用来编写Python代码;
  • 下载学习使用并适应使用PyCharm;
  • 将列表转换成字符串 ’ '.join(somelist);
  • 尝试使用string模块中的模板字符串Template().substitute(foo)进行格式化
  • - 用生成器解决八皇后问题还需要继续理解一下,特别是相比return

附录B:资料

  • 1、Github100天学Python项目:https://github.com/jackfrued/Python-100-Days
  • 2、菜鸟教程 python 3 教程:https://www.runoob.com/python3/python3-tutorial.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值