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

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. 打包一沓开源的 C/C++ 包管理工具送给你!

    本文作者:HelloGitHub-ChungZH 博客地址:https://chungzh.cn/ 包管理器可以帮助你更方便地安装依赖关系,并决定所安装的版本,提高你的开发幸福感.许多语言都有自己的包 ...

  2. input的onchange 和oninput事件

    一个小的功能,也体现了了这几天写程序过程中的遇到的一些常发事件,准备有时间研究一下jQuery和原生js,问题的出现:使用jQuery获取到的节点到底是属于什么,有些事件 居然不能用,就如我今天用到的 ...

  3. SparkSql学习笔记(包含IDEA编写的本地代码)

    Spark SQL and DataFrame 1.为什么要用Spark Sql 原来我们使用Hive,是将Hive Sql 转换成Map Reduce 然后提交到集群上去执行,大大简化了编写MapR ...

  4. 使用react定义组件的两种方式

    react组件的两种方式:函数定义,类定义 在定义一个组件之前,首先要明白一点:react元素(jsx)是react组件的最基本的组成单位 组件要求: 1,为了和react元素进行区分,组件名字首必须 ...

  5. ionic App 解决android端在真机上 tab处于顶部的Bug

    在app.js 页面中添加以下代码 .config(function($stateProvider, $urlRouterProvider,$ionicConfigProvider) { $ionic ...

  6. MSIL实用指南-生成while语句

    本篇讲解怎样生成while语句.while语句是编程语言中很重要的循环语句,它的结构是while(<表达式>) <语句或语句块> 当表达式的结果为true时就一直执行语句或语句 ...

  7. 设置VS2015背景图片(转载)

    设置方法很简单:安装扩展ClaudiaIDE 1.在这里下载扩展,https://visualstudiogallery.msdn.microsoft.com/9ba50f8d-f30c-4e33-a ...

  8. TypeScript语法基础

    什么是TypeScript? TypeScript是微软开发的一门编程语言,它是JavaScript的超集,即它基于JavaScript,拓展了JavaScript的语法,遵循ECMAScript规范 ...

  9. HDU-6229 ICPC-沈阳M- Wandering Robots 概率

    HDU - 6229 题意: 在一个n*n的地图中,有一个初始在(0,0)位子的机器人,每次等概率的向相邻的格子移动或者留在原地.问最后留在格子(x,y)(x+y>=n-1)的地方的概率. 思路 ...

  10. HDU - 2121 Ice_cream’s world II 无根最小树形图

    HDU - 2121 :http://acm.hdu.edu.cn/showproblem.php?pid=2121 比较好的朱刘算法blog:https://blog.csdn.net/txl199 ...