Python学习第十四课-面向对象四

一、多态

1.1 简介

  • 多态是面向对象的三大特性之一。从字面理解就是多种形态:一个对象可以以不同形态去呈现

  • 面向对象三大特性:

    • 1.封装 确保对象中数据的安全
    • 2.继承 保证了对象的扩展性
    • 3.多态 保证了程序的灵活性
  • Python中多态的特点:

    • 1、只关心的实例方法是否同名,不关心对象所属的类型;
    • 2、对象所属的类之间,继承关系可有可无;
    • 3、多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性较强;
    • 4、多态是调用方法的技巧,不会影响到类的内部设计。

1.2 练习

class Person(object):
    name = "人"

    def speak(self):
        print("{}会说话".format(self.name))


class Doctor(Person):  # 括号里是你要继承的父类的名称
    name = '医生'

    def speak(self):
        print("{}会安抚病人".format(self.name))

    def cure(self):
        print("{}会治病".format(self.name))


class Police(Person):
    name = '警察'

    def speak(self):
        print("{}会维护治安".format(self.name))


def method(obj):
    obj.speak()

a = Police()
method(a)

b = Doctor()
method(b)
'''
警察会维护治安
医生会安抚病人
'''
class Grandpa(object):
    def money(self):
        print('这是爷爷的钱')


class Father(Grandpa):
    def money(self):
        super().money() # 注释的话,儿子就继承不了爷爷的钱
        print('这是父亲的钱')


class Son(Father):
    def money(self):
        super().money()   # 只能继承上一级类
        print('这是儿子的钱')


def method(obj):
    obj.money()


grandpa = Grandpa()
father = Father()
son = Son()
# method(grandpa) # 这是爷爷的钱
#method(father) # 这是爷爷的钱 这是父亲的钱
method(son)
'''
这是爷爷的钱
这是父亲的钱
这是儿子的钱
'''

二、属性和方法

2.1类属性

  • 修改属性:对象. 属性名 = 属性值
    • 类属性:直接在类中定义的属性是类属性
    • 类属性可以通过类或类的实例访问到。但是类属性只能通过类对象来修改,不能通过实例对象来修改,方法通过实例对象修改

2.2 练习

class A(object):
    num = 0


a = A()
print(a.num)  # 通过实例对象访问类属性  # 0
print(A.num)  # 通过类对象访问类属性 # 0
a.num = 10  # 创建一个新的同名的num的实例属性
print(a.num)  # 实例属性 # 10
print(A.num)   # 类属性 0
A.num = 10  # 修改类属性
print(a.num)
print(A.num)
'''
0
0
10
0
10
10
'''

2.3 实例属性

  • 实例属性:通过实例对象添加的属性属于实例属性
  • 实例属性只能通过实例对象来访问和修改,类对象无法访问修改

2.4 练习

class A(object):
    num = 0


a = A()
print(a.num)  # 通过实例对象访问类属性  # 0
print(A.num)  # 通过类对象访问类属性 # 0
a.name = '紫紫'  # 创建一个新的同名的num的实例属性
print(a.name)  # 实例属性 # 紫紫
# print(A.name)   # AttributeError: type object 'A' has no attribute 'name'
'''
0
0
紫紫
'''

2.5 实例方法

  • 实例方法:在类中定义,以self为第一个参数的方法都是实例方法
  • 实例方法在调用时,Python会将调用对象以self传入
  • 实例方法可以通过类实例和类去调用
  • 当通过实例调用时,会自动将当前调用对象作为self传入
  • 当通过类调用时,不会自动传递self,我们必须手动传递self(加参数)

2.6 练习

class Person(object):
    name = "人"

    def speak(self):
        print("{}会说话".format(self.name))

class Doctor(Person):  # 括号里是你要继承的父类的名称
    name = '医生'

    def speak(self):
        print("{}会安抚病人".format(self.name))

    def cure(self):
        print("{}会治病".format(self.name))

class Police(Person):
    name = '警察'

    def speak(self):
        print("{}会维护治安".format(self.name))

def method(obj):
    obj.speak()

a = Police()
a.speak()
Police.speak(a)
#Police.speak() #TypeError: speak() missing 1 required positional argument: 'self'
'''
警察会维护治安
警察会维护治安
'''

2.7 类方法

  • 类方法:在类的内容以==@classmethod 来修饰==的方法属性类方法
  • 类方法第一个参数是cls也会自动被传递,cls就是当前的类对象。
  • 类方法和实例方法的区别:
    • 1.实例方法的第一个参数是self,类方法的第一个参数是cls
    • 2.类方法可以通过类去调用,也可以通过实例调用

2.8 练习

class Person(object):
    name = "人"

    def speak(self):
        print("{}会说话".format(self.name))


class Doctor(Person):  # 括号里是你要继承的父类的名称
    name = '医生'

    def speak(self):
        print("{}会安抚病人".format(self.name))

    def cure(self):
        print("{}会治病".format(self.name))


class Police(Person):
    name = '警察'

    def speak(self):
        print("{}会维护治安".format(self.name))
    @classmethod
    def run(cls):
        print("{}跑步飞快,可以轻易追上小偷".format(cls.name))
        


def method(obj):
    obj.speak()

a = Police()
a.speak()
Police.speak(a)
#Police.speak() #TypeError: speak() missing 1 required positional argument: 'self'
a.run()
Police.run()
'''
警察会维护治安
警察会维护治安
警察跑步飞快,可以轻易追上小偷
警察跑步飞快,可以轻易追上小偷
'''

2.9 静态方法

  • 在类中用==@staticmethod来修饰==的方法属于静态方法
  • 静态方法不需要指定任何的默认参数,静态方法可以通过类和实例调用
  • 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数
  • 静态方法一般都是些工具方法,和当前类无关

2.10 练习

class Person(object):
    name = "人"

    def speak(self):
        print("{}会说话".format(self.name))


class Doctor(Person):  # 括号里是你要继承的父类的名称
    name = '医生'

    def speak(self):
        print("{}会安抚病人".format(self.name))

    def cure(self):
        print("{}会治病".format(self.name))

class Police(Person):
    name = '警察'

    def speak(self):
        print("{}会维护治安".format(self.name))
    @classmethod
    def run(cls):
        print("{}跑步飞快,可以轻易追上小偷".format(cls.name))

    @staticmethod
    def staticmethod():
        print('我是静态方法')  # 静态方法,跟该类没关系,只是放到类里面,可以调用

def method(obj):
    obj.speak()

a = Police()
#Police.speak() #TypeError: speak() missing 1 required positional argument: 'self'
a.run()
Police.run()
a.staticmethod()
Police.staticmethod()
'''
警察会维护治安
警察会维护治安
警察跑步飞快,可以轻易追上小偷
警察跑步飞快,可以轻易追上小偷
'''

三、单例模式

  • 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

3.1 new()方法

  • 当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.new),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式
  • __new__()方法用于创建与返回一个对象。在类准备将自身实例化时调用。
    
    练习:
以下代码打印输出的顺序? C
A.__init__,__new__
B.__init__
C.__new__
D.__new__,__init__
class Demo(object):
	def __init__(self): #__init__()方法在对象创建的时候,自动调用
		print("__init__")
	def __new__(cls, *args, **kwargs):  # __new__()方法用于创建对象
		print("__new__")

d = Demo()
'''
__new__
'''

执行顺序:

__new__()方法用于创建对象
__init__()方法在对象创建的时候,自动调用
但是此处重写了父类的__new__()方法,覆盖了父类__new__()创建对象的功能,所以对象并没有创建成功。所以仅执行__new__()方法内部代码。

3.2 练习

class single(object):
    obj = None

    def __new__(cls, *args, **kwargs):
        if cls.obj is None:
            cls.obj = super().__new__(cls)
            return cls.obj
        else:
            return cls.obj


s1 = single()
s2 = single()
print(s1)
print(s2)
print(s1 is s2)
'''
<__main__.single object at 0x0000021C64510B00>
<__main__.single object at 0x0000021C64510B00>
True
'''

四、模块

4.1 简介

  • 模块化指一个完整的程序分解成一个个的小模块,通过将模块组合,来搭建出一个完整的程序
  • 模块化的特点:方便开发、方便维护、模块可以复用

4.2 模块的创建

  • 在Python当中一个py文件就是一个模块
  • 在一个模块中引入外部模块:import 模块名(模块名就是py文件)
  • 可以引入同一个模块多次,但是模块的实例只会创建一次
  • import 模块名
  • 在一个模块内部都有一个__name__。通过它我们可以获取模块的名字。
  • 如果py文件直接运行时,那么__name__默认等于字符串’main’。 name__属性值为__main(命名空间locals()的第一句“name : main”)的模块是主模块。一个程序中只有一个主模块

4.3 模块的使用

  • 访问模块中的变量 语法是 模块名.变量名
  • 访问模块中的函数 语法是 模块名.函数名
  • 访问模块中的对象 语法是 模块名.对象名
  • 我们也可以引入模块中部分内容 语法是 from 模块名 import 变量,变量…
  • 还有一种引入方式 语法 from 模块名 import 变量 as 别名(当导入的东西和当前模块冲突了,那么可以取别名)

需要掌握的模块: os, sys, time, random

4.4 import 语句

  • 想使用 Python 源文件,只需在另一个源文件里执行 import 语句,语法如下:
import module1[, module2[,... moduleN]
# @File : support.py
# @Description :
def print_func(par):
    print("Hello : ", par)
    return
# @File : test.py 
# @Description :
# 导入模块
import support

# 现在可以调用模块里包含的函数了
support.print_func("Runoob")

'''
Hello :  Runoob
'''
  • 当我们使用import语句的时候,Python解释器是怎样找到对应的文件的呢?

  • 这就涉及到Python的搜索路径,搜索路径是由一系列目录名组成的,Python解释器就依次从这些目录中去寻找所引入的模块。

  • 这看起来很像环境变量,事实上,也可以通过定义环境变量的方式来确定搜索路径。

  • 搜索路径是在Python编译或安装的时候确定的,安装新的库应该也会修改。搜索路径被存储在sys模块中的path变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MIANHUA_007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值