标签:属性 port com 命名方式 head icm 分解 下划线 静态成员变量
请看如下代码:
" _ooOoo_ "
" o8888888o "
" 88 . 88 "
" (| -_- |) "
" O\\ = /O "
" ____/`---‘\\____ "
" . ‘ \\| |// `. "
" / \\||| : |||// \\ "
" / _||||| -:- |||||- \\ "
" | | \\\\\\ - /// | | "
" | \\_| ‘‘\\---/‘‘ | | "
" \\ .-\\__ `-` ___/-. / "
" ___`. .‘ /--.--\\ `. . __ "
" ."" ‘< `.___\\_<|>_/___.‘ >‘"". "
" | | : `- \\`.;`\\ _ /`;.`/ - ` : | | "
" \\ \\ `-. \\_ __\\ /__ _/ .-` / / "
" ======`-.____`-.___\\_____/___.-`____.-‘====== "
" `=---=‘ "
" "
" ............................................. "
" 佛祖镇楼 BUG辟易 "
" 佛曰: "
" 写字楼里写字间,写字间里程序员; "
" 程序人员写程序,又拿程序换酒钱。 "
" 酒醒只在网上坐,酒醉还来网下眠; "
" 酒醉酒醒日复日,网上网下年复年。 "
" 但愿老死电脑间,不愿鞠躬老板前; "
" 奔驰宝马贵者趣,公交自行程序员。 "
" 别人笑我忒疯癫,我笑自己命太贱; "
" 不见满街漂亮妹,哪个归得程序员?"
运行后的现象:
定义函数的格式如下:
def 函数名():
代码
demo:
# 定义一个函数,能够完成打印信息的功能
def printInfo():
‘------------------------------------‘
‘ 人生苦短,我用Python‘
‘------------------------------------‘
定义了函数之后,就相当于有了一个具有某些功能的代码,想要让这些代码能够执行,需要调用它
调用函数很简单的,通过 函数名() 即可完成调用
demo:
# 定义完函数后,函数是不会自动执行的,需要调用它才可以
printInfo()
要求:定义一个函数,能够输出自己的姓名和年龄,并且调用这个函数让它执行
>>> def test(a,b):
..."用来完成对2个数求和"
...print("%d"%(a+b))
...
>>>
>>>test(11,22)
33
如果执行,以下代码
>>> help(test)
能够看到test函数的相关说明
Help on function testinmodule __main__:
test(a, b)
用来完成对2个数求和
(END)
思考一个问题,如下:
现在需要定义一个函数,这个函数能够完成2个数的加法运算,并且把结果打印出来,该怎样设计?下面的代码可以吗?有什么缺陷吗?
def add2num():
a =11
b =22
c = a+b
c
为了让一个函数更通用,即想让它计算哪两个数的和,就让它计算哪两个数的和,在定义函数的时候可以让函数接收数据,就解决了这个问题,这就是函数的参数
示例如下:
def add2num(a, b):
c = a+b
c
以调用上面的add2num(a, b)函数为例:
def add2num(a, b):
c = a+b
c
add2num(11,22)#调用带有参数的函数时,需要在小括号中,传递数据
调用带有参数函数的运行过程:
要求:定义一个函数,完成前2个数完成加法运算,然后对第3个数,进行减法;然后调用这个函数
>>> def test(a,b):
... print(a,b)
...
>>>test(1,2)
12
>>>test(b=1,a=2)
21
>>>
>>>test(b=1,2)
File"<stdin>", line1
SyntaxError: positional argument follows keyword argument
>>>
>>>
现实生活中的场景:
我给儿子10块钱,让他给我买包烟。这个例子中,10块钱是我给儿子的,就相当于调用函数时传递到参数,让儿子买烟这个事情最终的目标是,让他把烟给你带回来然后给你对么,,,此时烟就是返回值
开发中的场景:
定义了一个函数,完成了获取室内温度,想一想是不是应该把这个结果给调用者,只有调用者拥有了这个返回值,才能够根据当前的温度做适当的调整
综上所述:
想要在函数中把结果返回给调用者,需要在函数中使用return
如下示例:
def add2num(a, b):
c = a+b
returnc
或者
def add2num(a, b):
returna+b
在本小节刚开始的时候,说过的“买烟”的例子中,最后儿子给你烟时,你一定是从儿子手中接过来对么,程序也是如此,如果一个函数返回了一个数据,那么想要用这个数据,那么就需要保存
保存函数的返回值示例如下:
#定义函数
def add2num(a, b):
returna+b
#调用函数,顺便保存函数的返回值
result = add2num(100,98)
#因为result已经保存了add2num的返回值,所以接下来就可以使用了
result
结果:
198
函数根据有没有参数,有没有返回值,可以相互组合,一共有4种
此类函数,不能接收参数,也没有返回值,一般情况下,打印提示灯类似的功能,使用这类的函数
def printMenu():
print(‘--------------------------‘)
print(‘ xx涮涮锅 点菜系统‘)
print(‘‘)
print(‘ 1. 羊肉涮涮锅‘)
print(‘ 2. 牛肉涮涮锅‘)
print(‘ 3. 猪肉涮涮锅‘)
print(‘--------------------------‘)
结果:
此类函数,不能接收参数,但是可以返回某个数据,一般情况下,像采集数据,用此类函数
# 获取温度
def getTemperature():
#这里是获取温度的一些处理过程
#为了简单起见,先模拟返回一个数据
return24
temperature = getTemperature()
print(‘当前的温度为:%d‘%temperature)
结果:
当前的温度为:24
此类函数,能接收参数,但不可以返回数据,一般情况下,对某些变量设置数据而不需结果时,用此类函数
此类函数,不仅能接收参数,还可以返回某个数据,一般情况下,像数据处理并需要结果的应用,用此类函数
# 计算1~num的累积和
def calculateNum(num):
result =0
i =1
whilei<=num:
result = result + i
i+=1
returnresult
result = calculateNum(100)
print(‘1~100的累积和为:%d‘%result)
结果:
1~100的累积和为:5050
def testB():
print(‘---- testB start----‘)
print(‘这里是testB函数执行的代码...(省略)...‘)
print(‘---- testB end----‘)
def testA():
print(‘---- testA start----‘)
testB()
print(‘---- testA end----‘)
testA()
结果:
---- testA start----
---- testB start----
这里是testB函数执行的代码...(省略)...
---- testB end----
---- testA end----
# 打印一条横线
def printOneLine():
print("-"*30)
# 打印多条横线
def printNumLine(num):
i=0
# 因为printOneLine函数已经完成了打印横线的功能,
# 只需要多次调用此函数即可
whilei<num:
printOneLine()
i+=1
printNumLine(3)
# 求3个数的和
def sum3Number(a,b,c):
returna+b+c# return 的后面可以是数值,也可是一个表达式
# 完成对3个数求平均值
def average3Number(a,b,c):
# 因为sum3Number函数已经完成了3个数的就和,所以只需调用即可
# 即把接收到的3个数,当做实参传递即可
sumResult = sum3Number(a,b,c)
aveResult = sumResult/3.0
returnaveResult
# 调用函数,完成对3个数求平均值
result = average3Number(11,2,55)
print("average is %d"%result)
如果一个变量,既能在一个函数中使用,也能在其他的函数中使用,这样的变量就是全局变量
demo如下:
# 定义全局变量
a =100
def test1():
print(a)
def test2():
print(a)
# 调用函数
test1()
test2()
运行结果:
看如下代码:
既然全局变量,就是能够在所以的函数中进行使用,那么可否进行修改呢?
代码如下
全局变量global进行声明,否则出错强龙不压地头蛇>>>a =1
>>> def f():
...a +=1
...a
...
>>> f()
Traceback (most recent call last):
File"<stdin>", line1,in<module>
File"<stdin>", line2,inf
UnboundLocalError: local variable‘a‘referenced before assignment
>>>
>>>
>>>li = [1,]
>>> def f2():
...li.append(1)
...li
...
>>> f2()
[1,1]
>>> li
[1,1]
>>> def divid(a, b):
... shang = a//b
... yushu = a%b
...returnshang, yushu
...
>>>sh, yu = divid(5,2)
>>> sh
5
>>> yu
1
本质是利用了元组
调用函数时,缺省参数的值如果没有传入,则被认为是默认值。下例会打印默认的age,如果age没有被传入:
def printinfo( name, age = 35 ):
# 打印任何传入的字符串
"Name: ", name
"Age ", age
# 调用printinfo函数
printinfo(name="miki")
printinfo( age=9,name="miki")
以上实例输出结果:
Name: miki
Age35
Name: miki
Age9
>>> def printinfo(name, age=35, sex):
...name
...
File"<stdin>", line1
SyntaxError: non-default argument follows default argument
有时可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,声明时不会命名。
基本语法如下:
def functionname([formal_args,] *args, **kwargs):
"函数_文档字符串"
function_suite
return[expression]
加了星号(*)的变量args会存放所有未命名的变量参数,args为元组;而加**的变量kwargs会存放命名参数,即形如key=value的参数,kwargs为字典。
>>> def fun(a, b, *args, **kwargs):
..."""可变参数演示示例"""
..."a =", a
..."b =", b
..."args =", args
..."kwargs: "
...forkey, valueinkwargs.items():
...key,"=", value
...
>>>fun(1,2,3,4,5, m=6, n=7, p=8)# 注意传递的参数对应
a =1
b =2
args = (3,4,5)
kwargs:
p =8
m =6
n =7
>>>
>>>
>>>
>>>c = (3,4,5)
>>>d = {"m":6,"n":7,"p":8}
>>>fun(1,2, *c, **d)# 注意元组与字典的传参方式
a =1
b =2
args = (3,4,5)
kwargs:
p =8
m =6
n =7
>>>
>>>
>>>
>>>fun(1,2, c, d)# 注意不加星号与上面的区别
a =1
b =2
args = ((3,4,5), {‘p‘:8,‘m‘:6,‘n‘:7})
kwargs:
>>>
>>>
>>> def selfAdd(a):
..."""自增"""
... a += a
...
>>>a_int =1
>>> a_int
1
>>> selfAdd(a_int)
>>> a_int
1
>>>a_list = [1,2]
>>> a_list
[1,2]
>>> selfAdd(a_list)
>>> a_list
[1,2,1,2]
Python中函数参数是引用传递(注意不是值传递)。对于不可变类型,因变量不能修改,所以运算不会影响到变量自身;而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量。
>>> def selfAdd(a):
..."""自增"""
...a = a + a# 我们更改了函数体的这句话
...
>>>a_int =1
>>> a_int
1
>>> selfAdd(a_int)
>>> a_int
1
>>>a_list = [1,2]
>>> a_list
[1,2]
>>> selfAdd(a_list)
>>> a_list
[1,2]# 想一想为什么没有变呢?
通过前面的学习知道一个函数可以调用其他函数。
如果一个函数在内部不调用其它的函数,而是自己本身的话,这个函数就是递归函数。
举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * ... * n
解决办法1:
用lambda关键词能创建小型匿名函数。这种函数得名于省略了用def声明函数的标准步骤。
lambda函数的语法只包含一个语句,如下:
lambda[arg1 [,arg2,.....argn]]:expression
如下实例:
sum =lambdaarg1, arg2: arg1 + arg2
#调用sum函数
"Value of total : ", sum(10,20)
"Value of total : ", sum(20,20)
以上实例输出结果:
Value of total :30
Value of total :40
Lambda函数能接收任何数量的参数但只能返回一个表达式的值
匿名函数不能直接调用print,因为lambda需要一个表达式
2.>>> def fun(a, b, opt):
3...."a =", a
4...."b =", b
5...."result =", opt(a, b)
6....
7.>>>fun(1,2,lambdax,y:x+y)
8.a =1
9.b =2
10.result =3
stus = [
{"name":"zhangsan","age":18},
{"name":"lisi","age":19},
{"name":"wangwu","age":17}
]
>>>stus.sort(key =lambdax:x[‘name‘])
>>> stus
[{‘age‘:19,‘name‘:‘lisi‘}, {‘age‘:17,‘name‘:‘wangwu‘}, {‘age‘:18,‘name‘:‘zhangsan‘}]
>>>stus.sort(key =lambdax:x[‘age‘])
>>> stus
[{‘age‘:17,‘name‘:‘wangwu‘}, {‘age‘:18,‘name‘:‘zhangsan‘}, {‘age‘:19,‘name‘:‘lisi‘}]
def函数名():
语句
def函数名():
语句
return需要返回的数值
注意:
def函数名(形参列表):
语句
注意:
def函数名(形参列表):
语句
return需要返回的数值
函数名([实参列表])
提示:使用循环嵌套
提示:素数的特征是除了1和其本身能被整除,其它数都不能被整除的数
提示:
1.能被400整除的年份
2.能被4整除,但是不能被100整除的年份
以上2种方法满足一种即为闰年
20160818
是今年第x天
必须使用自定义函数,完成对程序的模块化
学生信息至少包含:姓名、年龄、学号,除此以外可以适当添加
必须完成的功能:添加、删除、修改、查询、退出
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件
open(文件名,访问模式)
示例如下:
f = open(‘test.txt‘,‘w‘)
说明:
|
访问模式 |
说明 |
|
r |
以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
|
w |
打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
|
a |
打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
|
rb |
以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
|
wb |
以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
|
ab |
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
|
r+ |
打开一个文件用于读写。文件指针将会放在文件的开头。 |
|
w+ |
打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
|
a+ |
打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
|
rb+ |
以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
|
wb+ |
以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
|
ab+ |
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
close( )
示例如下:
# 新建一个文件,文件名为:test.txt
f = open(‘test.txt‘,‘w‘)
# 关闭这个文件
f.close()
使用write()可以完成向文件写入数据
demo:
f = open(‘test.txt‘,‘w‘)
f.write(‘hello world, i am here!‘)
f.close()
运行现象:
注意:
使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据
demo:
f = open(‘test.txt‘,‘r‘)
content = f.read(5)
print(content)
print("-"*30)
content = f.read()
print(content)
f.close()
运行现象:
注意:
open(‘test.txt‘)就像read没有参数时一样,readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
#coding=utf-8
f = open(‘test.txt‘,‘r‘)
content = f.readlines()
print(type(content))
i=1
fortempincontent:
print("%d:%s"%(i, temp))
i+=1
f.close()
运行现象:
#coding=utf-8
f = open(‘test.txt‘,‘r‘)
content = f.readline()
print("1:%s"%content)
content = f.readline()
print("2:%s"%content)
f.close()
#coding=utf-8
oldFileName = input("请输入要拷贝的文件名字:")
oldFile = open(oldFileName,‘r‘)
# 如果打开文件
if oldFile:
# 提取文件的后缀
fileFlagNum = oldFileName.rfind(‘.‘)
iffileFlagNum >0:
fileFlag = oldFileName[fileFlagNum:]
# 组织新的文件名字
newFileName = oldFileName[:fileFlagNum] +‘[复件]‘+ fileFlag
# 创建新文件
newFile = open(newFileName,‘w‘)
# 把旧文件中的数据,一行一行的进行复制到新文件中
forlineContentinoldFile.readlines():
newFile.write(lineContent)
# 关闭文件
oldFile.close()
newFile.close()
在读写文件的过程中,如果想知道当前的位置,可以使用tell()来获取
# 打开一个已经存在的文件
f = open("test.txt","r")
str = f.read(3)
"读取的数据是 : ", str
# 查找当前位置
position = f.tell()
"当前文件位置 : ", position
str = f.read(3)
"读取的数据是 : ", str
# 查找当前位置
position = f.tell()
"当前文件位置 : ", position
f.close()
如果在读写文件的过程中,需要从另外一个位置进行操作的话,可以使用seek()
seek(offset, from)有2个参数
demo:把位置设置为:从文件开头,偏移5个字节
# 打开一个已经存在的文件
f = open("test.txt","r")
str = f.read(30)
"读取的数据是 : ", str
# 查找当前位置
position = f.tell()
"当前文件位置 : ", position
# 重新设置位置
f.seek(5,0)
# 查找当前位置
position = f.tell()
"当前文件位置 : ", position
f.close()
demo:把位置设置为:离文件末尾,3字节处
# 打开一个已经存在的文件
f = open("test.txt","r")
# 查找当前位置
position = f.tell()
"当前文件位置 : ", position
# 重新设置位置
f.seek(-3,2)
# 读取到的数据为:文件最后3个字节数据
str = f.read()
"读取的数据是 : ", str
f.close()
有些时候,需要对文件进行重命名、删除等一些操作,python的os模块中都有这么功能
os模块中的rename()可以完成对文件的重命名操作
rename(需要修改的文件名, 新的文件名)
importos
os.rename("毕业论文.txt","毕业论文-最终版.txt")
os模块中的remove()可以完成对文件的删除操作
remove(待删除的文件名)
importos
os.remove("毕业论文.txt")
实际开发中,有时需要用程序的方式对文件夹进行一定的操作,比如创建、删除等
就像对文件操作需要os模块一样,如果要操作文件夹,同样需要os模块
importos
os.mkdir("张三")
importos
os.getcwd()
importos
os.chdir("../")
importos
os.listdir("./")
importos
os.rmdir("张三")
#coding=utf-8
# 批量在文件名前加前缀
importos
funFlag =1# 1表示添加标志 2表示删除标志
folderName =‘./renameDir/‘
# 获取指定路径的所有文件名字
dirList = os.listdir(folderName)
# 遍历输出所有文件名字
fornameindirList:
name
iffunFlag ==1:
newName =‘[东哥出品]-‘+ name
eliffunFlag ==2:
num = len(‘[东哥出品]-‘)
newName = name[num:]
newName
os.rename(folderName+name, folderName+newName)
定义一个类,格式如下:
class 类名:
方法列表
demo:定义一个Car类
# 定义类
class Car:
# 方法
def getCarInfo(self):
print(‘车轮子个数:%d, 颜色%s‘%(self.wheelNum, self.color))
def move(self):
print("车正在移动...")
通过上一节课程,定义了一个Car类;就好比有车一个张图纸,那么接下来就应该把图纸交给生成工人们去生成了
python中,可以根据已经定义的类去创建出一个个对象
创建对象的格式为:
对象名=类名()
创建对象demo:
# 定义类
class Car:
# 移动
def move(self):
print(‘车在奔跑...‘)
# 鸣笛
def toot(self):
print("车在鸣笛...嘟嘟..")
# 创建一个对象,并用变量BMW来保存它的引用
BMW = Car()
BMW.color =‘黑色‘
BMW.wheelNum =4#轮子数量
BMW.move()
BMW.toot()
print(BMW.color)
print(BMW.wheelNum)
__init__()方法想一想:
在上一小节的demo中,我们已经给BMW这个对象添加了2个属性,wheelNum(车的轮胎数量)以及color(车的颜色),试想如果再次创建一个对象的话,肯定也需要进行添加属性,显然这样做很费事,那么有没有办法能够在创建对象的时候,就顺便把车这个对象的属性给设置呢?
答:
__init__()方法
def 类名:
#初始化函数,用来完成一些默认的设定
def __init__():
pass
__init__()方法的调用
# 定义汽车类
class Car:
def __init__(self):
self.wheelNum =4
self.color =‘蓝色‘
def move(self):
print(‘车在跑,目标:夏威夷‘)
# 创建对象
BMW = Car()
print(‘车的颜色为:%s‘%BMW.color)
print(‘车轮胎数量为:%d‘%BMW.wheelNum)
当创建Car对象后,在没有调用__init__()方法的前提下,BMW就默认拥有了2个属性wheelNum和color,原因是__init__()方法是在创建对象后,就立刻被默认调用了
既然在创建完对象后__init__()方法已经被默认的执行了,那么能否让对象在调用__init__()方法的时候传递一些参数呢?如果可以,那怎样传递呢?
# 定义汽车类
class Car:
def __init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def move(self):
print(‘车在跑,目标:夏威夷‘)
# 创建对象
BMW = Car(4,‘green‘)
print(‘车的颜色为:%s‘%BMW.color)
print(‘车轮子数量为:%d‘%BMW.wheelNum)
__init__()方法,在创建一个对象时默认被调用,不需要手动调用__init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中出了self作为第一个形参外还需要2个形参,例如__init__(self,x,y)__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去
__str__()方法class Car:
def __init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def __str__(self):
msg ="嘿。。。我的颜色是"+ self.color +"我有"+ int(self.wheelNum) +"个轮胎..."
returnmsg
def move(self):
print(‘车在跑,目标:夏威夷‘)
BMW = Car(4,"白色")
print(BMW)
看如下示例:
# 定义一个类
class Animal:
# 方法
def __init__(self, name):
self.name = name
def printName(self):
print(‘名字为:%s‘%self.name)
# 定义一个函数
def myPrint(animal):
animal.printName()
dog1 = Animal(‘西西‘)
myPrint(dog1)
dog2 = Animal(‘北北‘)
myPrint(dog2)
运行结果:
为了更好的理解面向对象编程,下面以“烤地瓜”为案例,进行分析
cook() : 把地瓜烤一段时间addCondiments() : 给地瓜添加配料__init__() : 设置默认的属性__str__() : 让print的结果看起来更好一些__init__()方法#定义`地瓜`类
class SweetPotato:
‘这是烤地瓜的类‘
#定义初始化方法
def __init__(self):
self.cookedLevel =0
self.cookedString ="生的"
self.condiments = []
#烤地瓜方法
def cook(self, time):
self.cookedLevel += time
ifself.cookedLevel >8:
self.cookedString ="烤成灰了"
elifself.cookedLevel >5:
self.cookedString ="烤好了"
elifself.cookedLevel >3:
self.cookedString ="半生不熟"
else:
self.cookedString ="生的"
把上面2块代码合并为一个程序后,在代码的下面添加以下代码进行测试
mySweetPotato = SweetPotato()
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)
完整的代码为:
class SweetPotato:
‘这是烤地瓜的类‘
#定义初始化方法
def __init__(self):
self.cookedLevel =0
self.cookedString ="生的"
self.condiments = []
#烤地瓜方法
def cook(self, time):
self.cookedLevel += time
ifself.cookedLevel >8:
self.cookedString ="烤成灰了"
elifself.cookedLevel >5:
self.cookedString ="烤好了"
elifself.cookedLevel >3:
self.cookedString ="半生不熟"
else:
self.cookedString ="生的"
# 用来进行测试
mySweetPotato = SweetPotato()
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)
在上面的代码最后面添加如下代码:
print("------接下来要进行烤地瓜了-----")
mySweetPotato.cook(4)#烤4分钟
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
addCondiments()方法和__str__()方法
def __str__(self):
msg = self.cookedString +" 地瓜"
iflen(self.condiments) >0:
msg = msg +"("
fortempinself.condiments:
msg = msg + temp +", "
msg = msg.strip(", ")
msg = msg +")"
returnmsg
def addCondiments(self, condiments):
self.condiments.append(condiments)
完整的代码如下:
class SweetPotato:
"这是烤地瓜的类"
#定义初始化方法
def __init__(self):
self.cookedLevel =0
self.cookedString ="生的"
self.condiments = []
#定制print时的显示内容
def __str__(self):
msg = self.cookedString +" 地瓜"
iflen(self.condiments) >0:
msg = msg +"("
fortempinself.condiments:
msg = msg + temp +", "
msg = msg.strip(", ")
msg = msg +")"
returnmsg
#烤地瓜方法
def cook(self, time):
self.cookedLevel += time
ifself.cookedLevel >8:
self.cookedString ="烤成灰了"
elifself.cookedLevel >5:
self.cookedString ="烤好了"
elifself.cookedLevel >3:
self.cookedString ="半生不熟"
else:
self.cookedString ="生的"
#添加配料
def addCondiments(self, condiments):
self.condiments.append(condiments)
# 用来进行测试
mySweetPotato = SweetPotato()
print("------有了一个地瓜,还没有烤-----")
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)
print("------接下来要进行烤地瓜了-----")
print("------地瓜经烤了4分钟-----")
mySweetPotato.cook(4)#烤4分钟
print(mySweetPotato)
print("------地瓜又经烤了3分钟-----")
mySweetPotato.cook(3)#又烤了3分钟
print(mySweetPotato)
print("------接下来要添加配料-番茄酱------")
mySweetPotato.addCondiments("番茄酱")
print(mySweetPotato)
print("------地瓜又经烤了5分钟-----")
mySweetPotato.cook(5)#又烤了5分钟
print(mySweetPotato)
print("------接下来要添加配料-芥末酱------")
mySweetPotato.addCondiments("芥末酱")
print(mySweetPotato)
可能你已经意识到,查看过着修改对象的属性(数据),有2种方法
SweetPotato.cookedLevel =5
SweetPotato.cook(5)
明明可以使用第1种方法直接修改,为什么还要定义方法来间接修改呢?
至少有2个原因:
cookedLevel = -3。这会使地瓜比以前还生,当然了这也没有任何意义,通过使用方法来进行修改,就可以在方法中进行数据合法性的检查
#定义一个home类
class Home:
def __init__(self, area):
self.area = area#房间剩余的可用面积
#self.light = ‘on‘ #灯默认是亮的
self.containsItem = []
def __str__(self):
msg ="当前房间可用面积为:"+ str(self.area)
iflen(self.containsItem) >0:
msg = msg +" 容纳的物品有: "
fortempinself.containsItem:
msg = msg + temp.getName() +", "
msg = msg.strip(", ")
returnmsg
#容纳物品
def accommodateItem(self,item):
#如果可用面积大于物品的占用面积
needArea = item.getUsedArea()
ifself.area > needArea:
self.containsItem.append(item)
self.area -= needArea
print("ok:已经存放到房间中")
else:
print("err:房间可用面积为:%d,但是当前要存放的物品需要的面积为%d"%(self.area, needArea))
#定义bed类
class Bed:
def __init__(self,area,name = ‘床‘):
self.name = name
self.area = area
def __str__(self):
msg =‘床的面积为:‘+ str(self.area)
returnmsg
#获取床的占用面积
def getUsedArea(self):
returnself.area
def getName(self):
returnself.name
#创建一个新家对象
newHome = Home(100)#100平米
print(newHome)
#创建一个床对象
newBed = Bed(20)
print(newBed)
#把床安放到家里
newHome.accommodateItem(newBed)
print(newHome)
#创建一个床对象
newBed2 = Bed(30,‘席梦思‘)
print(newBed2)
#把床安放到家里
newHome.accommodateItem(newBed2)
print(newHome)
#人类
class Ren:
def __init__(self,name):
self.name = name
self.xue =100
self.qiang =None
def __str__(self):
returnself.name +"剩余血量为:"+ str(self.xue)
def anzidan(self,danjia,zidan):
danjia.baocunzidan(zidan)
def andanjia(self,qiang,danjia):
qiang.lianjiedanjia(danjia)
def naqiang(self,qiang):
self.qiang = qiang
def kaiqiang(self,diren):
self.qiang.she(diren)
def diaoxue(self,shashangli):
self.xue -= shashangli
#弹夹类
class Danjia:
def __init__(self, rongliang):
self.rongliang = rongliang
self.rongnaList = []
def __str__(self):
return"弹夹当前的子弹数量为:"+ str(len(self.rongnaList)) +"/"+ str(self.rongliang)
def baocunzidan(self,zidan):
iflen(self.rongnaList) < self.rongliang:
self.rongnaList.append(zidan)
def chuzidan(self):
#判断当前弹夹中是否还有子弹
iflen(self.rongnaList) >0:
#获取最后压入到单间中的子弹
zidan = self.rongnaList[-1]
self.rongnaList.pop()
returnzidan
else:
returnNone
#子弹类
class Zidan:
def __init__(self,shashangli):
self.shashangli = shashangli
def shanghai(self,diren):
diren.diaoxue(self.shashangli)
#枪类
class Qiang:
def __init__(self):
self.danjia =None
def __str__(self):
ifself.danjia:
return"枪当前有弹夹"
else:
return"枪没有弹夹"
def lianjiedanjia(self,danjia):
ifnotself.danjia:
self.danjia = danjia
def she(self,diren):
zidan = self.danjia.chuzidan()
ifzidan:
zidan.shanghai(diren)
else:
print("没有子弹了,放了空枪....")
#创建一个人对象
laowang = Ren("老王")
#创建一个弹夹
danjia = Danjia(20)
print(danjia)
#循环的方式创建一颗子弹,然后让老王把这颗子弹压入到弹夹中
i=0
whilei<5:
zidan = Zidan(5)
laowang.anzidan(danjia,zidan)
i+=1
#测试一下,安装完子弹后,弹夹中的信息
print(danjia)
#创建一个枪对象
qiang = Qiang()
print(qiang)
#让老王,把弹夹连接到枪中
laowang.andanjia(qiang,danjia)
print(qiang)
#创建一个敌人
diren = Ren("敌人")
print(diren)
#让老王拿起枪
laowang.naqiang(qiang)
#老王开枪射敌人
laowang.kaiqiang(diren)
print(diren)
print(danjia)
laowang.kaiqiang(diren)
print(diren)
print(danjia)
如果有一个对象,当需要对其进行修改属性时,有2种方法
为了更好的保存属性安全,即不能随意修改,一般的处理方式为
class People(object):
def __init__(self, name):
self.__name = name
def getName(self):
returnself.__name
def setName(self, newName):
iflen(newName) >=5:
self.__name = newName
else:
print("error:名字长度需要大于或者等于5")
xiaoming = People("dongGe")
print(xiaoming.__name)
class People(object):
def __init__(self, name):
self.__name = name
def getName(self):
returnself.__name
def setName(self, newName):
iflen(newName) >=5:
self.__name = newName
else:
print("error:名字长度需要大于或者等于5")
xiaoming = People("dongGe")
xiaoming.setName("wanger")
print(xiaoming.getName())
xiaoming.setName("lisi")
print(xiaoming.getName())
__del__()方法创建对象后,python解释器默认调用__init__()方法;
当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法
import time
class Animal(object):
# 初始化方法
# 创建完对象后会自动被调用
def __init__(self, name):
print(‘__init__方法被调用‘)
self.__name = name
# 析构方法
# 当对象被删除时,会自动被调用
def __del__(self):
print("__del__方法被调用")
print("%s对象马上被干掉了..."%self.__name)
# 创建对象
dog = Animal("哈皮狗")
# 删除对象
del dog
cat = Animal("波斯猫")
cat2 = cat
cat3 = cat
print("---马上 删除cat对象")
del cat
print("---马上 删除cat2对象")
del cat2
print("---马上 删除cat3对象")
del cat3
print("程序2秒钟后结束")
time.sleep(2)
结果:
# 定义一个父类,如下:
class Cat(object):
def __init__(self, name, color="白色"):
self.name = name
self.color = color
def run(self):
print("%s--在跑"%self.name)
# 定义一个子类,继承Cat类如下:
class Bosi(Cat):
def setNewName(self, newName):
self.name = newName
def eat(self):
print("%s--在吃"%self.name)
bs = Bosi("印度猫")
print(‘bs的名字为:%s‘%bs.name)
print(‘bs的颜色为:%s‘%bs.color)
bs.eat()
bs.setNewName(‘波斯‘)
bs.run()
运行结果:
说明:
__init__方法,但是父类有,所以在子类继承父类的时候这个方法就被继承了,所以只要创建Bosi的对象,就默认执行了那个继承过来的__init__方法class Animal(object):
def __init__(self, name=‘动物‘, color=‘白色‘):
self.__name = name
self.color = color
def __test(self):
print(self.__name)
print(self.color)
def test(self):
print(self.__name)
print(self.color)
class Dog(Animal):
def dogTest1(self):
#print(self.__name) #不能访问到父类的私有属性
print(self.color)
def dogTest2(self):
#self.__test() #不能访问父类中的私有方法
self.test()
A = Animal()
#print(A.__name) #程序出现异常,不能访问私有属性
print(A.color)
#A.__test() #程序出现异常,不能访问私有方法
A.test()
print("------分割线-----")
D = Dog(name ="小花狗", color ="黄色")
D.dogTest1()
D.dogTest2()
Python中多继承的格式如下:
# 定义一个父类
class A:
def printA(self):
print(‘----A----‘)
# 定义一个父类
class B:
def printB(self):
print(‘----B----‘)
# 定义一个子类,继承自A、B
class C(A,B):
def printC(self):
print(‘----C----‘)
obj_C = C()
obj_C.printA()
obj_C.printB()
运行结果:
----A----
----B----
如果在上面的多继承例子中,如果父类A和父类B中,有一个同名的方法,那么通过子类去调用的时候,调用哪个?
#coding=utf-8
class base(object):
def test(self):
print(‘----base test----‘)
class A(base):
def test(self):
print(‘----A test----‘)
# 定义一个父类
class B(base):
def test(self):
print(‘----B test----‘)
# 定义一个子类,继承自A、B
class C(A,B):
pass
obj_C = C()
obj_C.test()
print(C.__mro__) #可以查看C类的对象搜索方法时的先后顺序
所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
#coding=utf-8
class Cat(object):
def sayHello(self):
print("halou-----1")
class Bosi(Cat):
def sayHello(self):
print("halou-----2")
bosi = Bosi()
bosi.sayHello()
#coding=utf-8
class Cat(object):
def __init__(self,name):
self.name = name
self.color =‘yellow‘
class Bosi(Cat):
def __init__(self,name):
# 调用父类的__init__方法1(python2)
#Cat.__init__(self,name)
# 调用父类的__init__方法2
#super(Bosi,self).__init__(name)
# 调用父类的__init__方法3
super().__init__(name)
def getName(self):
returnself.name
bosi = Bosi(‘xiaohua‘)
print(bosi.name)
print(bosi.color)
多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态
class F1(object):
def show(self):
‘F1.show‘
class S1(F1):
def show(self):
‘S1.show‘
class S2(F1):
def show(self):
‘S2.show‘
# 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
# 而实际传入的参数是:S1对象和S2对象
def Func(F1 obj):
"""Func函数需要接收一个F1类型或者F1子类的类型"""
obj.show()
s1_obj = S1()
Func(s1_obj)# 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
s2_obj = S2()
Func(s2_obj)# 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
class F1(object):
def show(self):
‘F1.show‘
class S1(F1):
def show(self):
‘S1.show‘
class S2(F1):
def show(self):
‘S2.show‘
def Func(obj):
obj.show()
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
在了解了类基本的东西之后,下面看一下python中这几个概念的区别
先来谈一下类属性和实例属性
在前面的例子中我们接触到的就是实例属性(对象属性),顾名思义,类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似。对于公有的类属性,在类外可以通过类对象和实例对象访问
class People(object):
name =‘Tom‘#公有的类属性
__age =12#私有的类属性
p = People()
print(p.name)#正确
print(People.name)#正确
print(p.__age)#错误,不能在类外通过实例对象访问私有的类属性
print(People.__age)#错误,不能在类外通过类对象访问私有的类属性
class People(object):
address =‘山东‘#类属性
def __init__(self):
self.name =‘xiaowang‘#实例属性
self.age =20#实例属性
p = People()
p.age =12#实例属性
print(p.address)#正确
print(p.name)#正确
print(p.age)#正确
print(People.address)#正确
print(People.name)#错误
print(People.age)#错误
class People(object):
country =‘china‘#类属性
print(People.country)
p = People()
print(p.country)
p.country =‘japan‘
print(p.country)#实例属性会屏蔽掉同名的类属性
print(People.country)
delp.country#删除实例属性
print(p.country)
类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以‘cls‘作为第一个参数的名字,就最好用‘cls‘了),能够通过实例对象和类对象去访问。
class People(object):
country =‘china‘
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
returncls.country
p = People()
p.getCountry()#可以用过实例对象引用
People.getCountry()#可以通过类对象引用
类方法还有一个用途就是可以对类属性进行修改:
class People(object):
country =‘china‘
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
returncls.country
@classmethod
def setCountry(cls,country):
cls.country = country
p = People()
p.getCountry()#可以用过实例对象引用
People.getCountry()#可以通过类对象引用
p.setCountry(‘japan‘)
print p.getCountry()
print People.getCountry()
结果显示在用类方法对类属性修改之后,通过类对象和实例对象访问都发生了改变
需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数
class People(object):
country =‘china‘
@staticmethod
#静态方法
def getCountry():
returnPeople.country
print People.getCountry()
从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用
# 定义车类
class Car(object):
# 定义车的方法
def move(self):
print("---车在移动---")
def stop(self):
print("---停车---")
# 定义一个销售车的店类
class CarStore(object):
def order(self):
self.car = Car()#找一辆车
self.car.move()
self.car.stop()
上面的4s店,只能销售那一种类型的车
如果这个是个销售北京现代品牌的车,比如伊兰特、索纳塔等,该怎样做呢?
# 定义伊兰特车类
class YilanteCar(object):
# 定义车的方法
def move(self):
print("---车在移动---")
def stop(self):
print("---停车---")
# 定义索纳塔车类
class SuonataCar(object):
# 定义车的方法
def move(self):
print("---车在移动---")
def stop(self):
print("---停车---")
# 定义一个销售北京现代车的店类
class CarStore(object):
def order(self, typeName):
#根据客户的不同要求,生成不同的类型的车
iftypeName =="伊兰特":
car = YilanteCar()
eliftypeName =="索纳塔":
car = SuonataCar()
returncar
这样做,不太好,因为当北京现代又生产一种新类型的车时,又得在CarStore类中修改,有没有好的解决办法呢?
# 定义伊兰特车类
class YilanteCar(object):
# 定义车的方法
def move(self):
print("---车在移动---")
def stop(self):
print("---停车---")
# 定义索纳塔车类
class SuonataCar(object):
# 定义车的方法
def move(self):
print("---车在移动---")
def stop(self):
print("---停车---")
# 用来生成具体的对象
def createCar(typeName):
iftypeName =="伊兰特":
car = YilanteCar()
eliftypeName =="索纳塔":
car = SuonataCar()
returncar
# 定义一个销售北京现代车的店类
class CarStore(object):
def order(self, typeName):
# 让工厂根据类型,生产一辆汽车
car = createCar(typeName)
returncar
# 定义伊兰特车类
class YilanteCar(object):
# 定义车的方法
def move(self):
print("---车在移动---")
def stop(self):
print("---停车---")
# 定义索纳塔车类
class SuonataCar(object):
# 定义车的方法
def move(self):
print("---车在移动---")
def stop(self):
print("---停车---")
# 定义一个生产汽车的工厂,让其根据具体的订单生产车
class CarFactory(object):
def createCar(self,typeName):
iftypeName =="伊兰特":
car = YilanteCar()
eliftypeName =="索纳塔":
car = SuonataCar()
returncar
# 定义一个销售北京现代车的店类
class CarStore(object):
def __init__(self):
#设置4s店的指定生产汽车的工厂
self.carFactory = CarFactory()
def order(self, typeName):
# 让工厂根据类型,生产一辆汽车
car = self.carFactory.createCar(typeName)
returncar
咋一看来,好像只是把生产环节重新创建了一个类,这确实比较像是一种编程习惯,此种解决方式被称作简单工厂模式
工厂函数、工厂类对具体的生成环节进行了封装,这样有利于代码的后需扩展,即把功能划分的更具体,4s店只负责销售,汽车厂只负责制造
当买车时,有很多种品牌可以选择,比如北京现代、别克、凯迪拉克、特斯拉等,那么此时该怎样进行设计呢?
# 定义一个基本的4S店类
class CarStore(object):
#仅仅是定义了有这个方法,并没有实现,具体功能,这个需要在子类中实现
def createCar(self, typeName):
pass
def order(self, typeName):
# 让工厂根据类型,生产一辆汽车
self.car = self.createCar(typeName)
self.car.move()
self.car.stop()
# 定义一个北京现代4S店类
class XiandaiCarStore(CarStore):
def createCar(self, typeName):
self.carFactory = CarFactory()
returnself.carFactory.createCar(typeName)
# 定义伊兰特车类
class YilanteCar(object):
# 定义车的方法
def move(self):
print("---车在移动---")
def stop(self):
print("---停车---")
# 定义索纳塔车类
class SuonataCar(object):
# 定义车的方法
def move(self):
print("---车在移动---")
def stop(self):
print("---停车---")
# 定义一个生产汽车的工厂,让其根据具体得订单生产车
class CarFactory(object):
def createCar(self,typeName):
self.typeName = typeName
ifself.typeName =="伊兰特":
self.car = YilanteCar()
elifself.typeName =="索纳塔":
self.car = SuonataCar()
returnself.car
suonata = XiandaiCarStore()
suonata.order("索纳塔")
工厂方法模式的定义定义了一个创建对象的接口(可以理解为函数),但由子类决定要实例化的类是哪一个,工厂方法模式让类的实例化推迟到子类,抽象的CarStore提供了一个创建对象的方法createCar,也叫作工厂方法。
子类真正实现这个createCar方法创建出具体产品。创建者类不需要直到实际创建的产品是哪一个,选择了使用了哪个子类,自然也就决定了实际创建的产品是什么。
。。。。。。。。
标签:属性 port com 命名方式 head icm 分解 下划线 静态成员变量
原文地址:https://www.cnblogs.com/wanglinjie/p/9107967.html