Python全栈工程师(多继承、函数重写)

简介: ParisGabriel            每天坚持手写  一天一篇  决定坚持几年 为了梦想为了信仰   开局一张图                      Python人工智能从入门到精通 补充:  对象 ------------------------...
ParisGabriel
 
 
 
         每天坚持手写  一天一篇  决定坚持几年 为了梦想为了信仰
 
   开局一张图

                      Python人工智能从入门到精通

 

补充:


 对象 ------------------------->
实例变量(属性)      类变量
实例方法          类方法( @classmethond)

静态方法( @staticmethond)(类内普通函数)

继承/派生
  单继承:
  一个子类只有一个父类
  一个父类可以有多个子类

 --------------------------------------------------------------------------------------------

 

用于类的函数:
  issublclass(cls, cls_or_tuple)
  判断这个类是否继承自其他类, 如果此cls是class
  或tuple中的一个派生子类, 返回True 否则返回False
示例:
  class A:
    pass
  class B(A):
    pass
  class C(B):
    pass

issublclass(C, B) # True
issublclass(B, C) # False
issublclass(C, (int, str)) # False
issublclass(C, (int, B, str)) # True

封装 enclosure
  封装是指隐藏类实现细节让使用者不关心这些细节
  封装的目的是让使用者通过尽可能少的方法(或属性)操作对象
私有属性和私有方法:
  python类中以双下划线(__)开头
  双下划线结尾的标识符为私有成员,私有成员或只能用类的方法进行访问和修改
  以__开头的实例变量有私有属性
  以__开头的方法有私有方法

示例:

class A:
    def __init__(self):
        self.__p1 = 100  # 私有属性

    def show_A(self):
        print("self.__p1", self.__p1)
        self.__m1()  # 可以调用自己的方法

    def __m1(self):  # 私有方法
        print("__m1(self)方法被调用")


a = A()
a.show_A()  # 100
# print(a.__p1)  # 出错 不能在类外部访问a.__p1私有属性 也不能在子类中访问
# a.__m1()  # 出错 不能在类外部访问a.__p1私有方法 也不能在子类中访问


class B(A):
    pass


b = B()
print(b.__p1)  # 出错,子类不能访问父类的私有成员
b.__m1()  # 出错

b._A__p1 = 200  # python的假封装可以用此方法访问
print(b.__p1)  # 200

多态polymorphic:
  什么是多态
    就是多种状态
    多态是指在继承/派生关系的类中,调用基类对象的方法,
    实际能够调用子类的覆盖方法的现象叫多态

状态:
  静态(编译时状态)执行速度快
  动态(运行时状态)执行速度慢
说明:
  多态调用方法与对象相关不与类相关
  Python的全部对象只有“运行时状态(动态)”
  没有C++语言里的“编译时状态(静态)”
  由于Python是解释执行的 是动态 没有静态
  是在运行时编译(解释执行)

示例:

# Pytgon中的运行时状态

class Shape:
    def draw(self):
        print("Shape的 draw 方法被调用")


class Point(Shape):
    def draw(self):
        print("画车")


class Circle(Shape):
    def draw(self):
        print("画圈")


# python无法实现静态 除非不出现任何覆盖
def my_draw(s):  # 其他静态语言 def my_draw(Circle s) 指定调用者 无法进行改变
    s.draw()  # 此处显示出"动态"


s1 = Circle()
s2 = Point()
my_draw(s1)  # 只有在调用时才能能确定调用哪一个
my_draw(s2)

面向对象不是编程而是一种思想
面向对象的语言的特征:
  继承
  封装
  多态

多继承:multiple inheritance
多继承是指一个子类继承两个或两个以上的基类
  语法:
    class 类名(基类名1, 基类名2, ...)
  说明:
    1.一个子类同时继承自多个父类,父类中的方法可以同时被继承下来
    2.如果两个父类中同时有同名方法,而在子类中又没有覆盖此方法时,
    调用结果难以确定  (也可以确定 C3算法)
示例:

class Car:
    def run(self, speed):
        print("汽车", speed, "Km/h 的速度行驶")


class Plane:
    def fly(self, height):
        print("飞机以海拔", height, "米高度飞行")


class PlaneCar(Plane, Car):
    '''同时继承Plane,Car的方法'''


p1 = PlaneCar()
p1.fly(10000)
p1.run(300)

 

多继承的问题(缺陷):
  标识符冲突的问题
  要谨慎使用继承
示例:

# 多继承名字冲突问题

class A:
    def m(self):
        print("A.m被调用")


class B:
    def m(self):
        print("B.m被调用")


class AB(A, B):  # 优先调用先出现的父类  有先后顺序
    pass


ab = AB()

ab.m()  # A.m被调用


class BA(B, A):
    pass


ba = BA()

ba.m()  # B.m被调用

多继承的MRO(Method Resolution Order):
  类的__mro__属性
    __mro__ 一个元组 里面存放类
    此属性用来记录方法查找顺序
示例:

class A:
    def go(self):
        print("A")


class B(A):
    def go(self):
        print("B")


class C(A):
    def go(self):
        print("C")


class D(B, C):
    def go(self):
        print("D")
        super().go()


d = D()
d.go()  # B


# 多继承的super调用关系一定是mro元组内的下一个类 和子父类没关系
# 如果没有方法则报错  调用算法(C3算法)
# 正常调用也是mro顺序

函数重写:
  在自定义类内添加相应的方法自定义类创建的实例
  像内建对象一样进行内建函数操作
对象转字符串函数:
  repr(obj) 返回一个能代表此对象的表达式字符串,通常eval(repr(obj))== obj
  (这个字符串通常给Python解释执行器运行用的)
  str(obj) 返回字符串(这个字符串通常给人阅读用的)

对象转字符串函数的重写方法:
  repr(obj) 函数的重写方法:
    def __repr__(self):

      pass
  str(obj) 函数的重写方法:
    def __str__(self):

      pass
  说明:
    1.str(obj)函数先查找obj.str()方法
    调用此方法并返回结果
    2.如果没有obj.__str__方法时返回obj.__repr__()
    方法的结果并返回
    3.如果obj.__repr__方法不存在,则调用obj类的__repr__
    实例方法显示:<__main__.XXXX object at 0x7f4b1c36fa90>
示例:

class MyNumber:
    def __init__(self, value):
        '构造函数,初始化MyNumber'
        self.data = value

    def __str__(self):
        '''转换为人能够识别的字符串'''
        print("__str__方法被调用")
        return "自定义数字类型对象:%d" % self.data

    def __repr__(self):
        '''转换为eval能够识别的字符串'''
        return 'MyNumber(%d)' % self.data


n1 = MyNumber(100)
n2 = MyNumber(200)
print("repr(n1):--->", repr(n1))
print("strr(n2):--->", str(n2))
print("strr(n2):--->", n2.__str__())

其他内建函数的重写方法:
__abs__        abs(obj)          函数
__len__        len(obj)          函数(必须返回整数)
__reversed__    reversed(obj)    函数(必须返回可迭代对象)
__round__         round(obj)        函数

示例:

# 函数重写
class MyNumber:

    def __init__(self, v):
        self.data = v

    def __repr__(self):
        return 'MyNumber(%d)' % self.data

    def __abs__(self):
        '''__abs__函数重写 求绝对值函数'''
        # return -self.data
        v = abs(self.data)
        return MyNumber(v)  # 创建一个新的MyNumber对象

    def __len__(self):
        '''__len__函数重写 求长度函数'''
        # return len(self.data)
        i = 0
        for x in self.data:
            i += 1
        return i


i1 = MyNumber(-10)
print(i1)
i2 = abs(i1)
print(i2)

i3 = MyNumber("123d5sa")
print(len(i3))

 


数据转换函数的重写:
__complex__     complex(obj)      函数
__int__         int(obj)        函数
__float__      float(obj)       函数
__bool__      bool(obj)       函数

示例:

数据转换构造函数重写
class MyNumber:

    def __init__(self, v):
        self.data = v

    def __repr__(self):
        return 'MyNumber(%d)' % self.data

    def __int__(self):
        # return 999999  # 可以自定义返回规则
        return self.data


n1 = MyNumber(100)
x = int(n1)
print(type(x))  # <class 'int'>


print(bool(n1))  # True
n2 = MyNumber(0)
print(bool(n2))  # True

# 默认返回  # True

 

布尔测试函数重写:
  格式
  __bool__
  作用:
    用于bool(obj)函数取值
    用于if语句的真值表达式中
  说明:
    1.当自定义的类内有__bool__(self)
    方法时,此方法的返回值为bool(obj)的返回值
    2.当不存在__bool__(self),bool(x)
    返回__len__(self)方法的返回值是否为零测试布尔值
    3.当不存在__len__方法时,则直接返回True
示例:

# bool(x)函数重写
class MyList:
    '''自定义类型的列表,用来保存数据,内部用列表来储存数据'''
    def __init__(self, iterable):
        self.data = [x for x in iterable]

    def __repr__(self):
        return " MyList(%s)" % self.data

    def __len__(self):
        '''返回长度'''
        print("__bool__方法被调用")
        return len(self.data)

    # def __bool__(self):
    #     print("__bool__方法被调用")
    #     return False  # 此处定义所有对象返回False

    def __bool__(self):
        print("__bool__方法被调用")
        for x in self.data:
            if not x:
                return False
        return True  # 自定义返回规则(这就是函数重写)


myl = MyList((1, 2, -3, 4, -5, 5))
print(myl)
print(bool(myl))
if myl:
    print("myl是真值")
else:
    print("myl是假值")

 

 

迭代器(高级):
  什么是迭代器:
    可以通过next(it)函数取值的对象就是迭代器
  迭代器协议:
    迭代器对象能够使用next函数获取下一项数据
    在没有下一项数据时触发一个StopIteration异常终止迭代的重写

迭代器协议实现方法:
   __next__(self) 方法来实现迭代协议

语法形式:
  class MyIterator:
    def __next__(self):
      迭代器协议
      return 数据
什么是可迭代对象:
  是指 iter(obj) 函数返回迭代对象(实例)
  可迭代对象内部需要定义__iter__(self)方法来返回迭代器对象

# 此示例示意让自定义的作为可迭代对象能让 for 语句迭代访问
class MyList:
    '''创建MyList类'''
    def __init__(self, iterable=()):
        '''初始化self 
           iterable:可迭代对象
        '''
        # 用iterable生成列表
        self.data = [x for x in iterable]

    def __repr__(self):
        '''返回一个MyList字符串'''
        return 'MyList(%s)' % self.data

    def __iter__(self):
        '''此方法必须返回一个迭代器对象
        此方法创建一个迭代器对象并返回
        '''
        return MyListIterator(self.data)


class MyListIterator:
    '''此类用来创建迭代器,此类型的迭代器可以迭代访问
    MyList类型的对象'''
    def __init__(self, lst):
        self.data = lst
        self.cur_index = 0  # 初始化迭代器的起始位置

    def __next__(self):
        '''此方法用于实现迭代器协议'''
        if self.cur_index >= len(self.data):
            # 如果索引越界就发终止迭代通知
            raise StopIteration
        value = self.data[self.cur_index]  # 要返回的值
        self.cur_index += 1
        return value


myl = MyList([0, -1, 2, -3])
print(myl)

# it = iter(myl)
# print(next(it))

for x in myl:  # 迭代访问自定义类型的可迭代对象
    print(x)

 

练习:
写一个类Bicycle类 ,有 run方法.调用时显示骑行里程km
class Bicycle:
  def run(self, km):
    print('自行车骑行了', km, '公里')
再写一个类EBicycle(电动自行车类), 在Bicycle类的基础上添加了电池电量 volume 属性, 有两个方法:
1. fill_charge(self, vol) 用来充电, vol为电量
2. run(self, km) 方法每骑行10km消耗电量1度,同时显示当前电量,当电量耗尽时调用 父类的run方法继续骑行

b = EBicycle(5) # 新买的电动有内有5度电
b.run(10) # 电动骑行了10km还剩 4 度电
b.run(100) #电动骑行了40km,还剩0度电,其余60用脚登骑行
b.fill_charge(10) # 又充了10度电
b.run(50) # 骑行了50公里剩5度电

答案:

 

class Bycycle:
    def run(self, km):
        '''自行车'''
        print("自行车骑行了", km, "公里")


class EBycyle(Bycycle):
    def __init__(self, volume=0):
        '''初始化电动车'''
        self.volume = volume
        print("新买的电动车有", volume, "度电")

    def fill_charge(self, vol):
        '''冲电'''
        self.volume += vol
        print("又冲了", vol, "度电")

    def run(self, km):
        self.volume -= (km / 10)  # 减去使用的电量
        x = abs(self.volume) * 10  # 计算超出的公里
        if self.volume < 0:  # 判断是否超出电量
            self.volume = 0
            print("电动车骑行了", km, "千米 还剩",
                  self.volume, "度电 其余", x, "千米用脚蹬")
        else:
            print("电动车骑行了", km, "千米 还剩",
                  self.volume, "度电")


b = EBycyle(10)
b.run(10)
b.run(100)
b.fill_charge(10)
b.run(50)
# 新买的电动车有 10 度电
# 电动车骑行了 10 千米 还剩 9.0 度电
# 电动车骑行了 100 千米 还剩 0 度电 其余 10.0 千米用脚蹬
# 又冲了 10 度电
# 电动车骑行了 50 千米 还剩 5.0 度电

b = EBycyle(50)
b.run(10)
b.run(100)
b.fill_charge(10)
b.run(50)
# 新买的电动车有 50 度电
# 电动车骑行了 10 千米 还剩 49.0 度电
# 电动车骑行了 100 千米 还剩 39.0 度电
# 又冲了 10 度电
# 电动车骑行了 50 千米 还剩 44.0 度电

 

 

练习:
1. 修改原有的学生信息管理系统, 将学生对象的,全部属性
都变为私有属性,不让外部直接访问来实现封装

源码:

  https://pan.baidu.com/s/1szQDS5cfzVHLlZrrJcCs8A

 

2. 写一个列表类MyList实现存储整数列表,写类的定义如下:
class MyList:
  def __init__(self, iterator):
    self.data = ...
让此类的对象能用for语句进行迭代访问

L = MyList(range(5))
print(L)
L2 = [x ** 2 for x in L]
print(L2) # [0, 1, 4, 9, 16]

 

答案:

class MyList:
    def __init__(self, iterable=()):
        self.lst = [x for x in iterable]

    def __repr__(self):
        return "%s" % self.lst

    def __iter__(self):
        return MyIterable(self.lst)


class MyIterable:
    def __init__(self, lst):
        self.lst = lst
        self.myindex = 0

    def __next__(self):
        if self.myindex >= len(self.lst):
            raise StopIteration
        value = self.lst[self.myindex]
        self.myindex += 1
        return value


L = MyList(range(5))
print(L)
for x in L:
    print(x)

L2 = [x ** 2 for x in L]
print(L2)

 

 

3. 写一个类Fibonacci 实现迭代器协议 ,此类的对象可以作为可迭代对象生成相应的斐波那契数
1 1 2 3 5
class Fibonacci:
  def __init__(self, n) # n代表数据的个数
...
...
实现如下操作:
for x in Fibonacci(10):
  print(x) # 1 1 3 5 8 ....
L = [x for x in Fibonacii(50)]
print(L)
F = fibonicci(30)
print(sum(F))

答案:

直接继承第二题的类

class Fibonicci(MyList):

    def __init__(self, n):
        L = [1, 1]
        for _ in range(n - 2):
            L.append(L[-1] + L[-2])
        self.lst = L


for x in Fibonicci(10):
    print(x)  # 1 1 3 5 8 ....
L = [x for x in Fibonicci(50)]
print(L)
F = Fibonicci(30)
print(F)
print(sum(F))

 

 

相关文章
|
1天前
|
开发者 Python
Python入门:8.Python中的函数
### 引言 在编写程序时,函数是一种强大的工具。它们可以将代码逻辑模块化,减少重复代码的编写,并提高程序的可读性和可维护性。无论是初学者还是资深开发者,深入理解函数的使用和设计都是编写高质量代码的基础。本文将从基础概念开始,逐步讲解 Python 中的函数及其高级特性。
Python入门:8.Python中的函数
|
1月前
|
存储 人工智能 Python
[oeasy]python061_如何接收输入_input函数_字符串_str_容器_ 输入输出
本文介绍了Python中如何使用`input()`函数接收用户输入。`input()`函数可以从标准输入流获取字符串,并将其赋值给变量。通过键盘输入的值可以实时赋予变量,实现动态输入。为了更好地理解其用法,文中通过实例演示了如何接收用户输入并存储在变量中,还介绍了`input()`函数的参数`prompt`,用于提供输入提示信息。最后总结了`input()`函数的核心功能及其应用场景。更多内容可参考蓝桥、GitHub和Gitee上的相关教程。
16 0
|
1月前
|
Python
[oeasy]python057_如何删除print函数_dunder_builtins_系统内建模块
本文介绍了如何删除Python中的`print`函数,并探讨了系统内建模块`__builtins__`的作用。主要内容包括: 1. **回忆上次内容**:上次提到使用下划线避免命名冲突。 2. **双下划线变量**:解释了双下划线(如`__name__`、`__doc__`、`__builtins__`)是系统定义的标识符,具有特殊含义。
32 3
|
1月前
|
JSON 监控 安全
深入理解 Python 的 eval() 函数与空全局字典 {}
`eval()` 函数在 Python 中能将字符串解析为代码并执行,但伴随安全风险,尤其在处理不受信任的输入时。传递空全局字典 {} 可限制其访问内置对象,但仍存隐患。建议通过限制函数和变量、使用沙箱环境、避免复杂表达式、验证输入等提高安全性。更推荐使用 `ast.literal_eval()`、自定义解析器或 JSON 解析等替代方案,以确保代码安全性和可靠性。
45 2
|
2月前
|
数据可视化 DataX Python
Seaborn 教程-绘图函数
Seaborn 教程-绘图函数
87 8
|
Python
Python全栈工程师(exercises)
# # 练习: # # 1. 用map函数求: # # 1**3 + 2**3 + 3 ** 3 + .... 9**3 的和 def add_(x): return x ** 3 print(sum(map(add_, range(1, 10)))) # # 2.
1476 0
|
存储 机器学习/深度学习 Python
Python全栈工程师 (exercises)
# 1:给定一个数,判断他是正数,负数,还是0 a = int(input("请输入一该个整数")) if a == 0: print(a, "是0") elif a > 0: print(a, "是正数") else: print(a, "是负数") # 练习2:输入一个季度的数字 输出该季度有那几个月 b = int(input("请输入一个季度:1.
2258 0
|
23天前
|
存储 缓存 Java
Python高性能编程:五种核心优化技术的原理与Python代码
Python在高性能应用场景中常因执行速度不及C、C++等编译型语言而受质疑,但通过合理利用标准库的优化特性,如`__slots__`机制、列表推导式、`@lru_cache`装饰器和生成器等,可以显著提升代码效率。本文详细介绍了这些实用的性能优化技术,帮助开发者在不牺牲代码质量的前提下提高程序性能。实验数据表明,这些优化方法能在内存使用和计算效率方面带来显著改进,适用于大规模数据处理、递归计算等场景。
58 5
Python高性能编程:五种核心优化技术的原理与Python代码
|
2月前
|
Python
[oeasy]python055_python编程_容易出现的问题_函数名的重新赋值_print_int
本文介绍了Python编程中容易出现的问题,特别是函数名、类名和模块名的重新赋值。通过具体示例展示了将内建函数(如`print`、`int`、`max`)或模块名(如`os`)重新赋值为其他类型后,会导致原有功能失效。例如,将`print`赋值为整数后,无法再用其输出内容;将`int`赋值为整数后,无法再进行类型转换。重新赋值后,这些名称失去了原有的功能,可能导致程序错误。总结指出,已有的函数名、类名和模块名不适合覆盖赋新值,否则会失去原有功能。如果需要使用类似的变量名,建议采用其他命名方式以避免冲突。
52 14
|
2月前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
116 2

热门文章

最新文章

推荐镜像

更多