序言:上个章节我们了解了面向对象的基础知识,这个章节我们将对面向对象的知识体系进行进一步的探究

1. @property装饰器

​ 上一章,我们在说属性的访问权限时,虽然我们不建议将属性设置为私有的,但是如果直接将属性直接暴露给外界也是有问题的,比如我们没办法检查赋给属性的值是否有效。我们之前的建议是将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的, 但是 校验属性的逻辑是在方法里的,我们没办法让其通过 实例.属性 进行赋值的时候 也去走我们 校验属性的那一套逻辑。如果我们想做到这一点,我们则需要使用 @property 装饰器来包装 getter 和 setter方法

# -*- coding:utf-8 -*-
"""
@Property 装饰器
version:0.1
author:coke
"""
class Person(object): def __init__(self,name,age):
self.__name = name
self.__age = age #访问器
@property
def name(self):
return self.__name #访问器 - getter方法
@property
def age(self):
return self.__age @age.setter
def age(self,age):
if age < 0 or age > 150:
print("年龄参数不正确")
return
self.__age = age def play(self):
if self.__age <= 16:
print("%s正在玩飞行棋."%self.__name)
else:
print("%s正在玩斗地主."%self.__name) def main():
person = Person("Jack",12)
person.age = -1
person.play() if __name__ == "__main__":
main()

输出结果

 

总结:@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性

 

2. 魔法方法

Python是一门动态语言。通常,动态语言允许我们在程序运行时给对象绑定新的属性或方法,当然也可以对已经绑定的属性和方法进行解绑定。但是如果我们需要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义__slots__变量来进行限定。需要注意的是__slots__的限定只对当前类的对象生效,对子类并不起任何作用。

# -*- coding:utf-8
"""
slots
version:0.1
author:coke
""" class Person(object):
# 限定Person对象只能绑定_name,_age 和 _gender属性
__slots__ = ('_name', '_age', '_gender') def __init__(self, name, age):
self._name = name
self._age = age @property
def name(self):
return self._name @property
def age(self):
return self._age @age.setter
def age(self, age):
self._age = age def play(self):
if self._age <= 16:
print("%s正在玩飞行棋,年龄%d" % (self._name, self._age))
else:
print("%s正在玩斗地主,年龄%d" % (self._name, self._age)) def main():
person = Person("Jack",18)
person.play() if __name__ == "__main__":
main()

总结:__slots__变量,可以来限制该class实例能添加的属性.

 

3. 类属性和实例属性

在前面的例子中我们接触到的就是实例属性(对象属性),顾名思义,类属性就是 类对象 所拥有的属性, 它被所有 类对象 的 实例对象 所共有,在内存中只存在一个副本 ,对于公有的类属性,在类外可以通过 类对象 和 实例对象 访问

 

类属性

class People(object):
address = "山东"
def __init__(self):
self.name = "xiaowang" #实例属性
self.age = 20 p = People()
p.age = 12
print(p.address) #正确
print(People.address) #正确
print(p.name) #正确
print(p.age) #正确 print(People.address)#正确
#print(People.age) #错误
#print(People.name) #错误

总结:实例属性,不能通过类对象.实例属性获取,类属性 既可以通过 类对象.类属性获取,也可以通过实例对象.类属性获取

 

通过实例(对象)去修改类属性

class People(object):
country = 'china' #类属性 print(People.country) #china
p = People()
print(p.country) #china
p.country = "japan"
print(p.country) #japan
print(People.country) #china
del p.country
print(p.country) #china

总结:类属性 虽然可以通过 实例对象.类属性访问,但是实例对象 无法对类属性进行修改和删除,若实例对象声明同名属性 则该属性属于 实例属性

 

4.静态方法和类方法

之前,我们在类中定义的方法都是对象方法,也就是说这些方法都是发送给对象的消息。实际上,我们写在类中的方法并不需要都是对象方法, 我们也可以根据需要创建 静态方法 和 类方法

 

静态方法

"""
静态方法
version:0.1
author:coke
"""
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 b + c > a and a + c > b def perimeter(self):
return self._a + self._b + self._c def area(self):
half = self.perimeter() / 2
return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c)) def main():
a,b,c = 3,4,5
if Triangle.is_valid(a,b,c):
t = Triangle(a,b,c)
print(t.perimeter())
print(t.area())
else:
print("无法构成三角形") if __name__ == '__main__':
main()

总结:通过修饰器@staticmethod来进行修饰 的方法,我们称其为静态方法,且静态方法可以通过类对象直接进行调用

 

类方法

"""
类方法
version:0.1
author:coke
"""
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):
ctimes = localtime(time())
return cls(ctimes.tm_hour, ctimes.tm_min, ctimes.tm_sec) def run(self):
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._hour += 1
self._minute = 0
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()

总结:用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数 ,能够通过实例对象和类对象去访问 ,并且 由于已经获得 cls参数 等于间接获得了 类信息,所以我们也可以通过类方法创建一个 类对象

 

5. 单继承和多继承

在程序中,继承描述的是事物之间的所属关系,例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物;同理,波斯猫和巴厘猫都继承自猫,而沙皮狗和斑点狗都继承足够,如下如所示:

单继承就是指 只继承一个父类信息,多继承则为 继承多个父类信息。要知道大部分程序语言 都只允许单继承,因为会出现钻石继承带来的问题。但是在python 中却意外的允许了 多继承的出现

 

单继承


# 继承object类父类信息
class Person(object):
"""人""" def __init__(self,name,age):
self._name = name
self._age = age @property
def name(self):
return self._name @property
def age(self):
return self._age @age.setter
def age(self,age):
self._age = age def play(self):
print("%s正在愉快的玩耍."% self._name) def watch_tv(self):
if self._age >= 18:
print("%s 正在看刺激的电影"%self._name)
else:
print("%s 正在看熊出没"%self._name) # (person) 继承person父类信息
class Student(Person):
def __init__(self,name,age,grade):
super().__init__(name,age)
self._grade = grade @property
def grade(self):
return self._grade @grade.setter
def grade(self):
self._grade = grade def study(self,course):
print("%s的%s正在学习%s."%(self._grade,self._name,course)) #继承 person父类信息
class Teacher(Person):
"""老师"""
def __init__(self,name,age,title):
super().__init__(name,age)
self._title = title @property
def title(self):
return self._title @title.setter
def title(self,title):
self._title = title def teacher(self,course):
print("%s%s正在讲%s."%(self._name,self._title,course)) def main():
stu = Student("Jack",15,"初二")
stu.study("数学")
stu.watch_tv()
t = Teacher("Marry",38,"专家教授")
t.teacher("语文")
t.watch_tv() if __name__ == "__main__":
main()

输出结果

 

多继承

#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类的对象搜索方法时的先后顺序

输出结果

总结:在出现钻石继承的问题时,调用谁,取决于 解析顺序(MRO)

 

6. 多态

子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。

"""
多态
version:0.1
author:coke
"""
from abc import ABCMeta,abstractmethod class Pet(object,metaclass=ABCMeta):
"""
宠物
"""
def __init__(self, nickname):
self._nickname = nickname @abstractmethod
def make_voice(self):
"""发出声音"""
pass class Dog(Pet):
"""狗"""
def make_voice(self):
print('%s: 汪汪汪...' %self._nickname) class Cat(Pet):
def make_voice(self):
print("%s:喵喵喵...." %self._nickname) def main():
#利用多态性质进行不同的声音的输出
pets = [Dog('旺财'),Cat('凯迪'),Dog('索拉')]
for pet in pets:
pet.make_voice() if __name__ == '__main__':
main()

解析:利用abc模块实现抽象类,abc.ABCMeta是实现抽象类的一个基础类, @abstractmethod定义抽象方法,无需实现功能,子类继承抽象类必须重写 抽象类的抽象方法。抽象方法就像是个模板方法

 

7. 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("波斯猫")
print("准备删除波斯猫了....")
del cat

输出结果

Python集训营45天—Day07 (面向对象编程进阶)的更多相关文章

  1. Python集训营45天—Day03

    目录 1. 分支结构 1.1 初步介绍 1.2 使用案例 1.3 练习 2.循环结构 1.1 初步介绍 1.2 使用案例 1. 分支结构 1.1 初步介绍 至今,我们所写的Python代码都是顺序执行 ...

  2. Python集训营45天—Day01

    目录 1. Python简介 2. 第一个Python程序 3. 知识点梳理 序言:未来是数据的世界,而python 是一门可以高效简洁处理数据的语言,博主打算花45天左右完成python学习的从0到 ...

  3. Python集训营45天—Day02

    目录 变量和运算符 1.1 初步介绍 1.2 使用案例 1.3 知识点梳理 1.4 练习 序言:这一章我们将学习变量以及常见的类型,我们将以案例和代码相结合的方式进行梳理,但是其中所有的案例和知识点 ...

  4. Python集训营45天—Day04 (函数)

    目录 1. 函数介绍 2. 函数的参数 3. 模块与函数 4. 递归函数 5. 匿名函数 6. 多返回值 python 的学习已经进入到第四天,前面几章我们已经学会了基本的变量操作,以及分支结构和循环 ...

  5. Python集训营45天—Day08 (文件操作)

    目录 1. 文件操作介绍 2. 文件的读写 2.1 文本文件 2.2 二进制文件 2.3 JSON文件 3. 文件的定位,重命名和删除 4. 文件夹的相关操作 1. 文件操作介绍 大家应该听说过一句话 ...

  6. 进击的Python【第七章】:Python的高级应用(四)面向对象编程进阶

    Python的高级应用(三)面向对象编程进阶 本章学习要点: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 一.面向对象高级语法部分 静态方法 ...

  7. Day7 - Python基础7 面向对象编程进阶

    Python之路,Day7 - 面向对象编程进阶   本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...

  8. python面向对象编程进阶

    python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 ...

  9. Python基础入门(6)- 面向对象编程

    1.初识面向对象 Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本篇随笔将详细介绍Python的面向对象编程. 如果你以前没有接触过面向对象 ...

随机推荐

  1. 从0开始学Git——Git的协同操作

    环境: test_git 目录下有个my-project 版本库 所有命令都在test_git目录下执行 本地协同操作 从远端仓库检出代码,或者克隆一个已有的版本库 拷贝一个已有的仓库 #格式: gi ...

  2. Vue实现静态数据分页

    <div style="padding:20px;" id="app"> <div class="panel panel-prima ...

  3. Vue+webpack项目的多环境打包配置

    背景:由于需要将应用部署到线上开发环境.线上测试环境.线上预发环境.线上生产环境,而每个环境的访问地址是不同的.如果每次更改请求地址未免有些繁琐,就考虑在本地进行一次性配置. 代码管理工具:git 代 ...

  4. centos7环境下redis的安装

    一.redis的安装 1.获取redis的安装包 wget http://download.redis.io/releases/redis-4.0.6.tar.gz,如果未安装wget,先安装wget ...

  5. atcoder D - 11(组合数学)

    题目链接:http://arc077.contest.atcoder.jp/tasks/arc077_b 题解:有n+1个数只有一个数字是有重复出现的,要求一共有多少不同的组合显然和这两个数的位置有关 ...

  6. 【Offer】[50-2] 【字符流中第一个只出现一次的字符】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次 ...

  7. java读写文件IO

    package Common.readFile; import Common.tool.User; import com.fasterxml.jackson.databind.ObjectMapper ...

  8. 前端自动化部署linux centOs + Jenkins + nignx + 单页面应用

    Jenkins是什么? Jenkins 是一款业界流行的开源持续集成工具,广泛用于项目开发,具有自动化构建.测试和部署等功能. 准备工作 Linux centOS系统阿里云服务器一个 码云一个存放vu ...

  9. 【第十篇】easyui-datagrid排序 (转)

    本文体验datagrid的排序. □ 思路 当点击datagrid的标题,视图传递给Controller的Form Data类似这样:page=1&rows=10&sort=Custo ...

  10. ORACLE SQL语句练习题

    --1:选择部门30中的所有员工select * from emp where deptno=30--2:列出所有办事员(clerk) 的姓名.编号和部门编号select empno,ename,de ...