Python学习--Day 22

163.python多继承与搜索顺序

  • 在python中,不支持方法重载,如果同名的函数会出现覆盖,后面的函数覆盖前面的函数。
class Person:
    def __init__(self,name):
        self.name = name
    def eat(self):
        print('eat1')
    def eat(self,food):
        print('eat2{}'.format(food))
p = Person('Amy')
p.eat() # 报错:TypeError: eat() missing 1 required positional argument: 'food'
  • 多继承是可以的,在python中可以实现多继承,即一个类继承很多其他类:
    示例:
class A:
    def test(self):
        print('__AAAA')
class B:
    def test1(self):
        print('___BBBN')
class C(A,B):
    def test2(self):
        print('__CCCC')
c = C()
c.test()
c.test1()
c.test2()
  • 多继承且函数同名的时候会调用哪一个?
    如下代码定义了Base类,A、B、C继承Base类,D继承A、B、C类,对对象d调用test打印得到A。
class Base:
    def test(self):
        print('Base')
class A(Base):
    def test(self):
        print('__AAAA')
class B(Base):
    def test(self):
        print('___BBB')
class C(Base):
    def test(self):
        print('__CCCC')
class D(A,B,C):
    pass
d =D()
d.test()
# 结果:
# __AAAA
  • import inspect中的inspect.getmro(类名)方法,可以以元组格式返回显示搜索顺序
    可以直接使用类名.__mro__,此方法不需要引入,推荐使用。总结:python允许多继承,使用格式:def 类名 (父类1,父类2.....),优先从自己的类定义的方法中寻找,再是父类1,随后是父类2…若父类2、父类1又分别继承其他类,则记住一个基本原则:python2中经典类(不标明object)是从左至右深度优先,新式类(标明继承object)是从左至右广度优先,而python3中所有都是从左到右广度优先,可以参考这篇文章
    同时弹幕上还有一些人说的是使用C3算法,暂时忽略,算是为以后留一个坑。
    代码使用该方法后,打印出的内容:
class Base:
    def test(self):
        print('Base')
class A(Base):
    def test(self):
        print('__AAAA')
class B(Base):
    def test(self):
        print('___BBBN')
class C(Base):
    def test(self):
        print('__CCCC')
class D(A,B,C):
    pass
d =D()
d.test()
import inspect
print(inspect.getmro(D))
# (<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Base'>, <class 'object'>)

164.多态

  • 面向对象的三大特点:多态、封装、继承
  • 多态:python的多态实现要借助isinatance,否则会报错,可以参考下面的代码:
class Person():
    def __init__(self,name):
        self.name = name
    def feed_pet(self,pet): # 不一定是pet类,其他类也可以,但是一定要使用isinatance进行判断,否则会报错
        if isinstance(pet,Pet):
            print('{} like pet {}, nickname is {}'.format(self.name,pet.role,pet.nickname))
        else:
            print('No')
class Pet:
    role = 'Pet'
    def __init__(self,nickname,age):
        self.nickname = nickname
        self.age = age
    def show(self):
        print('{} is {} years old'.format(self.nickname,self.age))
class Cat(Pet):
    role = 'cat'
    def catch_mouse(self):
        print('抓老鼠')
class Dog(Pet):
    role = 'dog'
    def watch_house(self):
        print('看家')
class Tiger:
    def eat(self):
        print("eat people")
cat = Cat('huahua',4)
dog = Dog('huihui',7)
tiger = Tiger()
person = Person('guigui')
person.feed_pet(cat)
person.feed_pet(tiger) # Tiger类也可以被接收,python具有一定的多态,

165.回顾

  • 内容回顾
    面向对象的特点:继承、封装、多态
    封装:私有化属性,定义公有的get和set方法,这地方的掌握比较差,要记忆。
    继承无法继承父类的私有化属性。
    调用父类的init方法可以有三种方式:super().__init__(参数)super(当前类名,self).__init__(参数)父类类名.__init__(self),最后一个方法必须传self
 class Student:
 	def __init__(self,age):
 		self.__age = age
 	@property
 	def age(self):
 		return self.__age
 	@age.setter
 	def age(self.age):
 		self.__age = age
 s = Student()
 s.age = 10
  • 有一个小问题要记录一下:
    这里返回是200,因为调用父类的方法,先查看父类的内容,而不是在子类的内容中使用父类的方法。
class Person():
    def __init__(self):
        self.__money = 200
        self.name = 'iming'
    def show1(self):
        print(self.name,self.__money)
class Student(Person):
    def __init__(self):
        super().__init__()
        self.__money = 800
    def show(self):
        print(self.__money)
s = Student()
s.show1() # 此处的结果是200,因为是调用了父类的show1函数并应用了父类的__money
  • 多继承,广度优先搜索。
  • 多态,可以使用isinstance()进行扩展。

166.单例

  • 单例模式:是一种开发模式(就是开发时候使用的一套程式或套路),简单来说就是一个对象多次用,以减少内存占用,创建对象的时候每次都使用一个地址,至始至终实例化同一个对象总是使用一个内存地址进行实例化。
  • 如何书写单例模式:
class Singeeton:
    __instance = None
    def __new__(cls):
        print('___new')
        if cls.__instance is None:
            print('1')
            cls.__instance = object.__new__(cls)
            return cls.__instance
        else:
            print('2')
            return cls.__instance
s = Singeeton()
s1 = Singeeton()
print(s)  # 使用的空间是一样的
print(s1) # 使用的空间是一样的
  • 单例的运行:
    第一次调用该类的时候,会查看__instance变量,此时是None,所以会使用new创建新的内存空间,return一个地址空间给init函数完成创建对象和初始化;第二次创建的时候,使用new返回的是同一个内存地址值,因此会在原来的内存地址上进行创建和初始化,这样就节省了内存空间。借用控制new函数在每次创建实例的时候返回一个固定的内存地址,实现了‘单例’。
  • 简化后的单例书写格式:简化了if-else语句:
class Singeeton:
    __instance = None
    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = object.__new__(cls)
            return cls.__instance

167.模块导入和使用

  • 在python中,模块是代码组织的一种方式,把功能近似的函数或者类放到同一个文件中,一个文件(.py)就是一个模块,模块名就是文件名去掉后缀py,这样做的好处是:提高代码的复用性、可维护性,解决了命名冲突,不同模块中相同的命名不会冲突。
  • 自定义模块:import 模块名,使用的时候要用:模块名.函数名模块名.类名模块名.变量名,着重记忆主文件中的调用方式。
# 文件名为calculate.py
# Day-22-01-module模块文件(以后的笔记都将在前两行注明文件名称以及模块文件的编号,没有注明的为主文件)
# 函数
def add(*args):
    if len(args) > 1:
        sum = 0
        for i in args:
            sum += i
        return sum
    else:
        print('2 need')
# 变量
number = 100
# 类
class jisuan():
    def test(self):
        print('jisuan')
# Day-22-01-module的主文件
list1 = [1,2,3,4,5,6]
import calculate
s = calculate.add(*list1)
print(s) # 结果:21
cal = calculate.number
print(cal) # 结果:100
s = calculate.jisuan()
s.test() # 结果:jisuan

168.模块导入

  • 模块导入的3种方法:①import 模块名;②from 模块名 import 变量/函数,在代码中直接使用变量;③from 模块名 import *——引入模块中的所有内容,如果想限制,可以在模块中使用__all__ = []限制*可以访问到的范围;④无论是import或是from的形式,都会将模块内容进行加载,如果不希望其进行调用,就会用到__name__ == '__main__',如果在其他模块中通过导入的方式调用的话,__name__就是模块名了。
  • 使用from 模块名 import 变量/函数的好处是可以方便我们书写代码:不必再使用calculate.add(),直接使用add就可以:
# Day-22-01-module的主文件
list1 = [1,2,3,4,5,6]
from calculate import add,number,jisuan
s = add(*list1)
print(s) # 结果:21
s = s + number 
print(s) # 结果:121
s = jisuan()
s.test() # 结果:jisuan
  • __name__ == '__main__'name__在自己的模块中使用叫__main,而在其他的模块之中使用,则是叫它的文件名:如下为示例:以Calculate.py为主文件,运行print(__name__),得到__main__,以调用Calculate的主文件中运行calculate下的print(__name__),得到calculate
  • 借助上面的知识点,如果在模块中有代码在引入的时候不希望被执行,可以在对应的执行函数上添加:if __name__ == '__main__':,以此来筛选。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值