Python学习之面向对象进阶
面向对象进阶当然是要谈谈面向对象的三大特性:封装、继承、多态
@property装饰器
python虽然不建议把属性和方法都设为私有的,但是完全暴露给外界也不好,这样,我们给属性赋值的有效性九无法保证,因此,为了使得对属性的访问既安全又方便,可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作,在python中,可以考虑使用@property包装器来包装getter和setter方法
class Person(object):
def __init__(self,name,age):
self._name=name
self._age=age
#访问器 - getter方法
@property
def name(self):
return self._name
@property
def age(self):
return self._age
# 修改器 - setter方法
@age.setter
def age(self,age):
self._age=age
def play(self):
if self._age <= 16:
print("%s正在玩吹泡泡!"%self._name)
else:
print("%s正在玩下象棋!"%self._name)
def main():
person=Person("wangbb",16)
person.play()
#调用setter修改器修改其属性
person.age=21
person.play()
#person.name='wbb' #AttributeError: can't set attribute
if __name__=='__main__':
main()
效果入下图:

__slots__魔法
__slots__魔法是为了让python这个动态语言,限定我们的自定义类型只能绑定特定的属性,而且只对当前类生效,对其子类没有限制作用
class Person(object):
# 限定Person类只能绑定_name,_age,_gender属性,
# 此处请注意,_name和name不是同一种属性,不能绑定name属性
__slots__ = ('_name','_age','_gender')
# Person类初始化
def __init__(self,name,age):
self._name=name
self._age=age
#访问器 - getter方法
@property
def name(self):
return self._name
@property
def age(self):
return self._age
# 修改器 - setter方法
@age.setter
def age(self,age):
self._age=age
def play(self):
if self._age <= 16:
print("%s正在玩吹泡泡!"%self._name)
else:
print("%s正在玩下象棋!"%self._name)
def main():
person=Person("wangbb",16)
person.play()
#调用setter修改器修改其属性
person.age=21
person.play()
person._gender='男'
#person._isgay=True AttributeError: 'Person' object has no attribute '_isgay' if __name__=='__main__':
main()
静态方法和类方法
定义在类中的方法有三种:对象方法(前面的大多数都是对象方法)、静态方法、类方法。关于静态方法,举个例子说明:我们定义一个“三角形”类,通过传入三条边长来构造三角形,并提供计算周长和面积的方法,但是传入的三条边长未必能构造出三角形对象,因此我们可以先写一个方法来验证三条边长是否可以构成三角形,这个方法很显然就不是对象方法,因为在调用这个方法时三角形对象尚未创建出来(因为都不知道三条边能不能构成三角形),所以这个方法是属于三角形类而并不属于三角形对象的。我们可以使用静态方法来解决这类问题:
from math import sqrt
class Triangle(object):
def __init__(self,a,b,c):
self._a=a
self._b=b
self._c=c
#静态方法
@staticmethod
def is_valid(a,b,c):
return a + b > c and a + c > b and b + c > a
def perimeter(self):
return self._a+self._b+self._c
def area(self):
href=self.perimeter()/2
return sqrt(href*(href-self._a)*(href-self._b)*(href-self._c))
def main():
a,b,c=3,4,5
#静态方法和类方法都是通过给类发消息来调用的
if Triangle.is_valid(a,b,c):
triangle=Triangle(a,b,c)
print("三角形的周长是:",triangle.perimeter())
# 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数
print(Triangle.perimeter(triangle))
print("三角形的面积是:",triangle.area())
print(Triangle.area(triangle))
else:
print("不好意思,不能构成三角形!")
if __name__=='__main__':
main()

和静态方法比较类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息的对象(类本身也是一个对象,有的地方也称之为类的元数据对象),通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象:
from time import time, localtime, sleep class Clock(object):
"""数字时钟""" def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second @classmethod
def now(cls):
ctime = localtime(time())
return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec) 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 show(self):
"""显示时间"""
return '%02d:%02d:%02d' % \
(self._hour, self._minute, self._second) def main():
# 通过类方法创建对象并获取系统时间
clock = Clock.now()
while True:
print(clock.show())
sleep(1)
clock.run() if __name__ == '__main__':
main()
类之间的关系
简单的说,类和类之间的关系有三种:is-a、has-a和use-a关系。
- is-a关系也叫继承或泛化,比如学生和人的关系、手机和电子产品的关系都属于继承关系。
- has-a关系通常称之为关联,比如部门和员工的关系,汽车和引擎的关系都属于关联关系;关联关系如果是整体和部分的关联,那么我们称之为聚合关系;如果整体进一步负责了部分的生命周期(整体和部分是不可分割的,同时同在也同时消亡),那么这种就是最强的关联关系,我们称之为合成关系。
- use-a关系通常称之为依赖,比如司机有一个驾驶的行为(方法),其中(的参数)使用到了汽车,那么司机和汽车的关系就是依赖关系。
继承和多态
python可以在已有类的基础上创建新类,这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写。提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有的更多的能力,子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。
Python从语法层面并没有像Java或C#那样提供对抽象类的支持,但是我们可以通过abc模块的ABCMeta元类和abstractmethod包装器来达到抽象类的效果,如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)。
"""
某公司有三种类型的员工 分别是部门经理、程序员和销售员
需要设计一个工资结算系统 根据提供的员工信息来计算月薪
部门经理的月薪是每月固定15000元
程序员的月薪按本月工作时间计算 每小时150元
销售员的月薪是1200元的底薪加上销售额5%的提成
"""
from abc import ABCMeta,abstractmethod
class employee(object,metaclass=ABCMeta):
def __init__(self,name):
self._name=name
@property
def name(self):
return self._name
@abstractmethod
def get_salary(self):
pass
class manger(employee):
def get_salary(self):
return 15000.0
class programer(employee):
def __init__(self,name,work_hour=0):
super().__init__(name)
self._work_hour=work_hour
def get_salary(self):
return 150.0*self._work_hour
@property
def work_hour(self):
return self._work_hour
@work_hour.setter
def work_hour(self,work_hour):
self._work_hour=work_hour if work_hour>0 else 0
class salesman(employee):
def __init__(self,name,sales=0):
super().__init__(name)
self._sales=sales
def get_salary(self):
return 1200.0+self._sales*0.05
@property
def sales(self):
return self._sales
@sales.setter
def sales(self,sales):
self._sales=sales if sales >0 else 0
def main():
emps=[manger('wbb'),programer('bb'),salesman('lj')]
for emp in emps:
if isinstance(emp,programer):
emp.work_hour=int(input("请输入%s本月工作时长:"%emp.name))
elif isinstance(emp,salesman):
emp.sales=float(input("请输入%s本月的销售量:"%emp.name))
print("%s本月的工资为:¥%s元"%(emp.name,emp.get_salary()))
if __name__=='__main__':
main()

Python学习之面向对象进阶的更多相关文章
- python学习总结(面向对象进阶)
-------------------类属性和实例属性关系------------------- 1.类属性和实例属性关系 1.实例属性 实例对象独有的属性 2.类属性 ...
- Python学习之==>面向对象编程(二)
一.类的特殊成员 我们在Python学习之==>面向对象编程(一)中已经介绍过了构造方法和析构方法,构造方法是在实例化时自动执行的方法,而析构方法是在实例被销毁的时候被执行,Python类成员中 ...
- Python学习day15-函数进阶(3)
figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...
- Python学习day14-函数进阶(2)
figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...
- Python学习day13-函数进阶(1)
Python学习day13-函数进阶(1) 闭包函数 闭包函数,从名字理解,闭即是关闭,也就是说把一个函数整个包起来.正规点说就是指函数内部的函数对外部作用域而非全局作用域的引用. 为函数传参的方式有 ...
- 周末班:Python基础之面向对象进阶
面向对象进阶 类型判断 issubclass 首先,我们先看issubclass() 这个内置函数可以帮我们判断x类是否是y类型的子类. class Base: pass class Foo(Base ...
- Python中级 —— 01面向对象进阶
面向对象进阶 总结.补充(http://blog.csdn.net/fgf00/article/details/52479307) 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 ...
- python 学习分享-面向对象2
面向对象进阶 静态方法 一种普通函数,就位于类定义的命名空间中,它不会对任何实例类型进行操作.使用装饰器@staticmethod定义静态方法.类对象和实例都可以调用静态方法: class Foo: ...
- 学习PYTHON之路, DAY 8 - PYTHON 基础 8 (面向对象进阶)
类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...
随机推荐
- .NET知识梳理——4.特性Attribute
1. 特性 1.1 特性Attribute 特性就是一个类,继承自Attribute抽象类(该类无抽象方法.避免实例化),约定俗成用Attribute类结尾,标记时可省略掉Attribu ...
- JavaScript变量的传递方式
废话不多说,直接上案例: [案例] 1.访问变量 按值: function addM(num) { num += 5; return num; } var cnt = 10; var result = ...
- Python开发坦克大战
Python不仅能开发网站,爬虫数据分析等,他其实也可以写游戏,接下来就给大家分享下坦克大战的代码: PS:很多人在学习Python的过程中,往往因为遇问题解决不了或者没好的教程从而导致自己放弃,为此 ...
- liunx 中设置zookeeper 自启动(service zookeeper does not support chkconfig)
在liunx 上设置zookeeper 自启动 1.进入目录 cd /etc/init.d 2.创建一个文件 vim zookeeper 3.编辑zookeepr 文件 连接liunx使用的软件是fi ...
- 洛谷P1583 魔法照片
https://www.luogu.org/problem/P1583 话不多说,其实就是模拟,然后,各种繁琐 #include<bits/stdc++.h> using namespac ...
- day22 定时任务
检查软件是否安装 cronie [root@oldboyedu ~]# rpm -qa cronie cronie-1.4.11-19.el7.x86_64 [root@oldboyedu ~]# r ...
- HTTP响应头 状态码
HTTP 简介 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传 ...
- FineUIPro/Mvc/Core v6.1.0 发布了!
FineUIPro/Mvc/Core v6.1.0 正式发布了(2019-12-25),这个版本主要是BUG修正,并增加了一些新特性,建议升级到此版本. 在列举新版本特性之前,我们先来回顾下每次发布大 ...
- JS高级---bind方法的使用
bind方法的使用 //通过对象,调用方法,产生随机数 function ShowRandom() { //1-10的随机数 this.number = parseInt(Math.random() ...
- strtotime中的一些坑
monday: 获取到的时间戳是下一个周一,如果当天是周一则获取到当天. last monday:获取上一个周一时间戳,如果当天是周一获取到的也是上一个周一时间戳. next monday:获取下一个 ...