标签:属性 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 test
inmodule __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>", line
1
SyntaxError: positional argument follows keyword argument
>>>
>>>
现实生活中的场景:
我给儿子10块钱,让他给我买包烟。这个例子中,10块钱是我给儿子的,就相当于调用函数时传递到参数,让儿子买烟这个事情最终的目标是,让他把烟给你带回来然后给你对么,,,此时烟就是返回值
开发中的场景:
定义了一个函数,完成了获取室内温度,想一想是不是应该把这个结果给调用者,只有调用者拥有了这个返回值,才能够根据当前的温度做适当的调整
综上所述:
想要在函数中把结果返回给调用者,需要在函数中使用return
如下示例:
def add2num(a, b):
c = a+b
return
c
或者
def add2num(a, b):
return
a+b
在本小节刚开始的时候,说过的“买烟”的例子中,最后儿子给你烟时,你一定是从儿子手中接过来对么,程序也是如此,如果一个函数返回了一个数据,那么想要用这个数据,那么就需要保存
保存函数的返回值示例如下:
#定义函数
def add2num(a, b):
return
a+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():
#这里是获取温度的一些处理过程
#为了简单起见,先模拟返回一个数据
return
24
temperature = getTemperature()
print(
‘当前的温度为:%d‘%temperature)
结果:
当前的温度为
:
24
此类函数,能接收参数,但不可以返回数据,一般情况下,对某些变量设置数据而不需结果时,用此类函数
此类函数,不仅能接收参数,还可以返回某个数据,一般情况下,像数据处理并需要结果的应用,用此类函数
# 计算1~num的累积和
def calculateNum(num):
result =
0
i =
1
while
i<=num:
result = result + i
i+=
1
return
result
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函数已经完成了打印横线的功能,
# 只需要多次调用此函数即可
while
i<num:
printOneLine()
i+=
1
printNumLine(
3)
# 求3个数的和
def sum3Number(a,b,c):
return
a+b+c
# return 的后面可以是数值,也可是一个表达式
# 完成对3个数求平均值
def average3Number(a,b,c):
# 因为sum3Number函数已经完成了3个数的就和,所以只需调用即可
# 即把接收到的3个数,当做实参传递即可
sumResult = sum3Number(a,b,c)
aveResult = sumResult/
3.0
return
aveResult
# 调用函数,完成对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>", line
1,
in<module>
File
"<stdin>", line
2,
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
...return
shang, 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
Age
35
Name: miki
Age
9
>>> def printinfo(name, age=35, sex):
...name
...
File
"<stdin>", line
1
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: "
...for
key, value
inkwargs.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
fortemp
incontent:
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(
‘.‘)
if
fileFlagNum >
0:
fileFlag = oldFileName[fileFlagNum:]
# 组织新的文件名字
newFileName = oldFileName[:fileFlagNum] +
‘[复件]‘+ fileFlag
# 创建新文件
newFile = open(newFileName,
‘w‘)
# 把旧文件中的数据,一行一行的进行复制到新文件中
for
lineContent
inoldFile.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(需要修改的文件名, 新的文件名)
import
os
os.rename(
"毕业论文.txt",
"毕业论文-最终版.txt")
os模块中的remove()可以完成对文件的删除操作
remove(待删除的文件名)
import
os
os.remove(
"毕业论文.txt")
实际开发中,有时需要用程序的方式对文件夹进行一定的操作,比如创建、删除等
就像对文件操作需要os模块一样,如果要操作文件夹,同样需要os模块
import
os
os.mkdir(
"张三")
import
os
os.getcwd()
import
os
os.chdir(
"../")
import
os
os.listdir(
"./")
import
os
os.rmdir(
"张三")
#coding=utf-8
# 批量在文件名前加前缀
import
os
funFlag =
1# 1表示添加标志 2表示删除标志
folderName =
‘./renameDir/‘
# 获取指定路径的所有文件名字
dirList = os.listdir(folderName)
# 遍历输出所有文件名字
for
name
indirList:
name
if
funFlag ==
1:
newName =
‘[东哥出品]-‘+ name
elif
funFlag ==
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) +
"个轮胎..."
return
msg
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
if
self.cookedLevel >
8:
self.cookedString =
"烤成灰了"
elif
self.cookedLevel >
5:
self.cookedString =
"烤好了"
elif
self.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
if
self.cookedLevel >
8:
self.cookedString =
"烤成灰了"
elif
self.cookedLevel >
5:
self.cookedString =
"烤好了"
elif
self.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 +
" 地瓜"
if
len(self.condiments) >
0:
msg = msg +
"("
for
temp
inself.condiments:
msg = msg + temp +
", "
msg = msg.strip(
", ")
msg = msg +
")"
return
msg
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 +
" 地瓜"
if
len(self.condiments) >
0:
msg = msg +
"("
for
temp
inself.condiments:
msg = msg + temp +
", "
msg = msg.strip(
", ")
msg = msg +
")"
return
msg
#烤地瓜方法
def cook(self, time):
self.cookedLevel += time
if
self.cookedLevel >
8:
self.cookedString =
"烤成灰了"
elif
self.cookedLevel >
5:
self.cookedString =
"烤好了"
elif
self.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)
if
len(self.containsItem) >
0:
msg = msg +
" 容纳的物品有: "
for
temp
inself.containsItem:
msg = msg + temp.getName() +
", "
msg = msg.strip(
", ")
return
msg
#容纳物品
def accommodateItem(self,item):
#如果可用面积大于物品的占用面积
needArea = item.getUsedArea()
if
self.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)
return
msg
#获取床的占用面积
def getUsedArea(self):
return
self.area
def getName(self):
return
self.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):
return
self.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):
if
len(self.rongnaList) < self.rongliang:
self.rongnaList.append(zidan)
def chuzidan(self):
#判断当前弹夹中是否还有子弹
if
len(self.rongnaList) >
0:
#获取最后压入到单间中的子弹
zidan = self.rongnaList[-
1]
self.rongnaList.pop()
return
zidan
else
:
return
None
#子弹类
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):
if
self.danjia:
return
"枪当前有弹夹"
else
:
return
"枪没有弹夹"
def lianjiedanjia(self,danjia):
if
not
self.danjia:
self.danjia = danjia
def she(self,diren):
zidan = self.danjia.chuzidan()
if
zidan:
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):
return
self.__name
def setName(self, newName):
if
len(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):
return
self.__name
def setName(self, newName):
if
len(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):
return
self.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):
return
cls.country
p = People()
p.getCountry()
#可以用过实例对象引用
People.getCountry()
#可以通过类对象引用
类方法还有一个用途就是可以对类属性进行修改:
class People(object):
country =
‘china‘
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
return
cls.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():
return
People.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):
#根据客户的不同要求,生成不同的类型的车
if
typeName ==
"伊兰特":
car = YilanteCar()
elif
typeName ==
"索纳塔":
car = SuonataCar()
return
car
这样做,不太好,因为当北京现代又生产一种新类型的车时,又得在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):
if
typeName ==
"伊兰特":
car = YilanteCar()
elif
typeName ==
"索纳塔":
car = SuonataCar()
return
car
# 定义一个销售北京现代车的店类
class CarStore(object):
def order(self, typeName):
# 让工厂根据类型,生产一辆汽车
car = createCar(typeName)
return
car
# 定义伊兰特车类
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):
if
typeName ==
"伊兰特":
car = YilanteCar()
elif
typeName ==
"索纳塔":
car = SuonataCar()
return
car
# 定义一个销售北京现代车的店类
class CarStore(object):
def __init__(self):
#设置4s店的指定生产汽车的工厂
self.carFactory = CarFactory()
def order(self, typeName):
# 让工厂根据类型,生产一辆汽车
car = self.carFactory.createCar(typeName)
return
car
咋一看来,好像只是把生产环节重新创建了一个类,这确实比较像是一种编程习惯,此种解决方式被称作简单工厂模式
工厂函数、工厂类对具体的生成环节进行了封装,这样有利于代码的后需扩展,即把功能划分的更具体,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()
return
self.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
if
self.typeName ==
"伊兰特":
self.car = YilanteCar()
elif
self.typeName ==
"索纳塔":
self.car = SuonataCar()
return
self.car
suonata = XiandaiCarStore()
suonata.order(
"索纳塔")
工厂方法模式
的定义定义了一个创建对象的接口
(可以理解为函数),但由子类决定要实例化的类是哪一个,工厂方法模式让类的实例化推迟到子类,抽象的CarStore提供了一个创建对象的方法createCar,也叫作工厂方法
。
子类真正实现这个createCar方法创建出具体产品。创建者类不需要直到实际创建的产品是哪一个,选择了使用了哪个子类,自然也就决定了实际创建的产品是什么。
。。。。。。。。
标签:属性 port com 命名方式 head icm 分解 下划线 静态成员变量
原文地址:https://www.cnblogs.com/wanglinjie/p/9107967.html