面向对象
类是对象的蓝图和模板 有了类就可以创建对象。定义类需要的两件事情:数据抽象和行为抽象;数据抽象-抽取对象共同的静态特征-名词-属性;行为抽象-抽取对象共有的动态特征-动词-方法;定义类的关键字是 -class-类名(每个单词首字母大写)。
-step1:定义类
class Student(object):
# 构造方法(构造器/构造子)-constructor
# 调用该方法的时候不是直接使用方法的名字而是使用类的名字
-Step2.调用构造方法创建对象
def __init__(self,name,age):
#给对象绑定属性
self.name=name
self.age=age
def study(self,course):
print('%s正在学习%s:'% (self.name, course))
#我们定义一个方法就代表对象可以接受这个消息
#对象的方法的第一个参数都是统一self
#它代表了接受消息的对象-对象.消息(参数)
def watch_av(self):
if self.age>=18:
print('%s正在观看美国大片'% self.name)
else:
print('%s推荐你观看熊出没' % self.name)
def main():
-Step3.给对象发消息
#实际上条用的是Student类中__init__方法
stu1=Student('罗哈',38)
#通过给对象发消息让对象完成某些工作
#解决任何的问题都是通过让对象去做事情
stu1.name='白元芳'#定义一个对象,没有给其赋年龄
stu2=Student('王大锤',16)
stu1.study('python 程序设计')#给对象stu1送入course参数
stu2.study('HTML网页设计')
stu2.watch_av()
if __name__ == '__main__':
main()
结果:
白元芳正在学习python 程序设计:
王大锤正在学习HTML网页设计:
王大锤推荐你观看熊出没
我们定义一个类实际上是把数据的函数绑在一起,形成一个逻辑上的整体,这个整体就叫做对象,而且将来任何时候想要使用这种对象直接复用这个类就可以了。
"""
有一个游泳池半径为r,过道半径为r+3,在修建一堵围墙,且过道造价每25.5元每平米,围墙造价为32.5每平米,求过道的造价,围墙的造价 以及总造价。
"""
from math import pi#引入数学常量pi
class Circle(object):
def __init__(self,radius):
"""创建构造器"""
self._radius=radius
def area(self):
"""求面积的函数"""
return pi * self._radius**2
def perometer(self):
"""求周长的函数"""
return 2 * pi* self._radius
def main():
r = float(input('请输入游泳池的半径:'))
big=Circle(r+3)
small=Circle(r)
print('围墙的造价为:%.2f元'% (big.perometer()*32.5))
print('过道的造价为:%.2f元' % ((big.area()-small.area())*25.5))
if __name__ == '__main__':
main()
练习;
1. 定义一个类描述数字的时钟
class Clock(object):
"""
数字时钟
"""
def __init__(self, hour=0, minute=0, second=0):
"""
构造器
:param hour: 时
:param minute: 分
:param second: 秒
"""
self._hour = hour
self._minute = minute
self._second = second
def run(self):
"""走字"""
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
def __str__(self):
"""显示时间"""
return '%02d:%02d:%02d' % \
(self._hour, self._minute, self._second)
#自己定义时间
def main():
clock = Clock()
while True:
print(clock)
sleep(1)
clock.run()
if __name__ == '__main__':
main()
结果为:
00:00:00
00:00:01
00:00:02
00:00:03
00:00:04
00:00:05
#与系统时间保持一致,只需将主函数改为一下即可:
def main():
localtime = time.localtime(time.time())#取当本地时间的时分秒
hour=localtime[3]
minute=localtime[4]
second=localtime[5]
local=Clock(hour,minute,second)
while True:
print(local)
sleep(1)
local.run()
结果:
19:25:37
19:25:38
19:25:39
19:25:40
19:25:41
2.定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法
from math import sqrt
class Point(object):
def __init__(self, x=0, y=0):
"""
构造器
:param x: 横坐标
:param y: 纵坐标
"""
self.x = x
self.y = y
def move_to(self, x, y):
"""
移动到指定位置
:param x: 新的横坐标
"param y: 新的纵坐标
"""
self.x = x
self.y = y
def move_by(self, dx, dy):
"""
移动指定的增量
:param dx: 横坐标的增量
"param dy: 纵坐标的增量
"""
self.x += dx
self.y += dy
def distance_to(self, other):
"""
计算与另一个点的距离
:param other: 另一个点
"""
dx = self.x - other.x
dy = self.y - other.y
return sqrt(dx ** 2 + dy ** 2)
def __str__(self):
return '(%s, %s)' % (str(self.x), str(self.y))
def main():
p1 = Point(3, 5)
p2 = Point()
print(p1)
print(p2)
p2.move_by(-1, 2)
print(p2)
print(p1.distance_to(p2))
if __name__ == '__main__':
main()
3. 定义一个类 时间自己设定的倒计时器
from time import sleep
class Timepiece(object):
def __init__(self, hour=0, minute=0, second=0):
"""构造器"""
self._hour = hour
self._minute = minute
self._second = second
def run(self):
self._second -= 1
if self._second==-1:
self._second=59
self._minute-=1
if self._minute==-1:
self._minute=59
self._hour-=1
if self._hour==0:
return '时间到!'
def __str__(self):
return '%02d:%02d:%02d' % (self._hour, self._minute, self._second)
def main():
clock=Timepiece(1,30,30)
while True:
print(clock)
sleep(1)
clock.run()
if __name__ == '__main__':
main()
结果为:
01:30:30
01:30:29
01:30:28
01:30:27
01:30:26
可变参数
当参数的个数不确定时,我们一般是使用可变参数进行传参。例如:
#当传入为列表时,在参数前加一个*
def my_sum(*args):
total=0
for val in args:
total+=val
return total
def main():
my_list = [1, 25, 3, 40, 5]
print(my_sum(*my_list))
结果为:
74
关键字参数
根据参数名来决定如何执行
def say_hello(**kwargs):
print(kwargs)
for key in kwargs:
print(key, '--->', kwargs[key])
if 'name' in kwargs:
print('您好,%s!' % kwargs['name'])
elif 'age' in kwargs:
age = kwargs['age']
if age <= 16:
print('你还是个小屁孩')
else:
print('你是一个成年人')
else:
print('请提供个人信息')
def main():
say_hello(name='骆昊', age=38)
param = {
'name': '王大锤', 'age': 16, 'tel': '133445566'}
# 如果希望将一个字典作为关键字参数传入 与要在参数前方两个*
say_hello(**param)
结果:
{
'name': '骆昊', 'age': 38}
name ---> 骆昊
age ---> 38
您好,骆昊!
{
'name': '王大锤', 'age': 16, 'tel': '133445566'}
name ---> 王大锤
age ---> 16
tel ---> 133445566
您好,王大锤!
命名关键字参数
在函数进行参数初始化时,你可以在其中任意一个位置加上’‘并添加上逗号,在‘’前的在主函数进行传参时可不指名参数名,但在‘*’之后的,必须指明参数名,否则会报错。
def foo(a, b, c, *, name, age):
print(a + b + c)
print(name, ':', age)
def main():
foo(1,2,3,name='hao',age=38)
foo(1,2,3,'hao',38)
结果为:
6
hao:38
TypeError: foo() takes 3 positional arguments but 5 were given
装饰器
之前我们讨论过Python中属性和方法访问权限的问题,虽然我们不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效。我们之前的建议是将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作。如果要做到这点,就可以考虑使用@property包装器来包装getter和setter方法,使得对属性的访问既安全又方便,代码如下所示。
class Student(object):
def __init__(self, name, age):
#构造器
self._name = name
self._age = age
# 属性访问器
@property
def name(self):
return self._name
# 属性修改器
@name.setter
def name(self, name):
self._name = name if 2 <= len(name) <= 4 else '无