35.python全栈之路:面对对象进阶

面对对象进阶

1.多继承中的self

class A:
    def bar(self):
        print(‘BAR‘)
        self.f1()
‘‘‘
self本身代表的D类的对象d1
d1如果要在他的父类中去寻找f1
首先应该去C类
‘‘‘

class B(A):
    def f1(self):
        print(‘B‘)

class C:
    def f1(self):
        print(‘C‘)

class D(C, B):
        pass

d1 = D()
d1.bar()
  流程分析:
  1. d1 = D(),最终找到了object里面的__init__方法创建了对象d1
  2. d1.bar(),执行bar方法,先去C里找,再去B里面找,最后在A中找到了
  3. 执行A中的bar方法,遇到self.f1(),此时self依然表示对象d1
  4. 依然先去C里面找方法f1,最终在C中找到了

2.构造方法

  2.1 普通构造方法
class Animal:
    def __init__(self):
        print(‘A构造方法‘)
        self.ty = ‘动物‘

class Cat(Animal):
    def __init__(self):
        print(‘B构造方法‘)
        self.n = ‘猫‘

a = Animal()
c = Cat()
print(a.__dict__)
print(c.__dict__)
‘‘‘
A构造方法
B构造方法
{‘ty‘: ‘动物‘}
{‘n‘: ‘猫‘}
‘‘‘
  2.2 如果我们想将父类的字段ty封装子类Cat创建的对象中去呢?
class Animal:
    def __init__(self):
        print(‘A构造方法‘)
        self.ty = ‘动物‘

class Cat(Animal):
    def __init__(self):
        print(‘B构造方法‘)
        self.n = ‘猫‘
        self.ty = ‘动物‘
        # 执行父类的构造方法

a = Animal()
c = Cat()
print(a.__dict__)
print(c.__dict__)
‘‘‘
A构造方法
B构造方法
{‘ty‘: ‘动物‘}
{‘n‘: ‘猫‘, ‘ty‘: ‘动物‘}
‘‘‘
  2.3 如果父类的字段较多,创建子类的时候想继承这些字段,需要重复的代码量很大

   我们可以执行父类的构造方法super

class Animal:
    def __init__(self):
        print(‘A构造方法‘)
        self.ty = ‘动物‘
        self.chi = ‘吃‘
        self.he = ‘喝‘
        self.la = ‘拉‘

# 方法1
class Cat(Animal):
    def __init__(self):
        print(‘B构造方法‘)
        self.n = ‘猫‘
        super(Cat, self).__init__()  # 找到Cat的父类,执行其父类的构造方法

‘‘‘
方法2
class Cat(Animal):
    def __init__(self):
        print(‘B构造方法‘)
        self.n = ‘猫‘
        Animal.__init__(self)
‘‘‘

a = Animal()
c = Cat()
print(a.__dict__)
print(c.__dict__)
‘‘‘
A构造方法
B构造方法
A构造方法
{‘ty‘: ‘动物‘, ‘chi‘: ‘吃‘, ‘he‘: ‘喝‘, ‘la‘: ‘拉‘}
{‘n‘: ‘猫‘, ‘ty‘: ‘动物‘, ‘chi‘: ‘吃‘, ‘he‘: ‘喝‘, ‘la‘: ‘拉‘}
‘‘‘

3.面对对象中的反射

  3.1基本用法
class Foo:
    def __init__(self, name):
        # 类的字段
        self.name = name

    def show(self):
        print(‘show‘)

obj = Foo(‘alex‘)

# 通过类,找到类的方法
r1 = hasattr(Foo, ‘show‘)
print(r1)
‘‘‘
True
‘‘‘

# 通过对象,既可以找到对象的成员,也可以找到类里的成员
r2 = hasattr(obj, ‘name‘)  # 找到对象的成员
r3 = hasattr(obj, ‘show‘)  # 通过类对象指针,可以找到类的方法
print(r2, r3)
‘‘‘
True True
‘‘‘
  3.2 通过字符导入模块,用反射操作类的成员

class Foo:
    def __init__(self, name):
        # 类的字段
        self.name = name

    def show(self):
        print(‘show‘)

testmoudle.py

# 通过字符串导入模块
c = __import__(‘testmoudle‘, fromlist=True)  # 模块名有嵌套的话
# 通过反射获取模块中的类
class_name = getattr(c, ‘Foo‘)
# 根据类创建一个对象
obj = class_name(‘alex‘)
# 通过反射获取name对应的值
val = getattr(obj, ‘name‘)
print(val)
‘‘‘
alex
‘‘‘

  

4.类的成员

  成员:

    字段:普通字段(每个对象都不同的数据),静态字段(每个对象都有一份

    方法:普通方法(使用对象封装的数据),静态方法(无需使用对象封装的内容),类方法(自动将类名传入

    特性:将方法以字段的形式调用 

  快速判断是由类执行还是对象执行:

    有self,对象调用

    无self,类调用

class Province:
    # 静态字段
    country = ‘China‘

    def __init__(self, name):
        # 普通字段
        self.name = name
        # self.country = ‘china‘

    # 普通方法
    def show(self):
        print(‘show‘)

    # 类方法
    @classmethod
    def xxoo(cls):  # cls == class
        print(‘xxoo‘)

    # 静态方法
    @staticmethod
    def xo(arg1, arg2):
        print(‘xo‘)

    def start(self):
        temp = ‘%s sb‘ % self.name
        return temp

    # 特性,将方法伪造成字段,用于获取
    @property
    def end(self):
        temp = ‘%s sb‘ % self.name
        return temp

    @end.setter
    def end(self, value):
        print(value)

hebei = Province(‘河北‘)

Province.xo(1, 2)

# 方法本需要加括号访问
# @property后 可以以访问字段的方式去访问
obj = Province(‘alex‘)
ret1 = obj.start()
ret2 = obj.end
print(ret1, ret2)

# 获取字段
# print(obj.name)
# 设置字段
# obj.name = ‘123‘
# print(obj.name)

print(obj.end)  # 获取
obj.end = 123  # 设置

‘‘‘
************ 规范 **************
1.通过类访问的有: 静态字段,静态方法,类方法(静态方法的特殊形式)
    Province.country
    Province.xo(1, 2)
2.通过对象访问的有:普通字段,类的方法
    hebei.name
    hebei.show()
************ 规范 **************

3.静态字段存在的意义
    将每个对象都存在的东西只在类里保存一份就行

4.静态方法存在的意义
    普通方法执行前需要先创建对象
    静态方法不需要先创建对象,类
    似于将一个普通的函数放在类中,
        在c#和java中非常有用因为他们只能
        面向对象,必须要创建类

5.类方法和静态方法一样,只能通过类访问
    区别在于
        静态方法,参数任意
        类方法会自动获取当前类的类名,作为参数传入

‘‘‘

  

5.成员修饰符

  对于私有的,只有自己可以访问,其他(包括子类)都不能访问

  5.1 对于字段
class Foo:
    A = ‘aa‘
    __A = ‘aa‘

    def __init__(self):
        self.name = ‘alex‘
        self.__name = ‘wuwen‘

    def aaa(self):
        print(Foo.__A)
        print(self.__name)

    def bbb(self):
        pass

class Bar(Foo):

    def fetch(self):
        print(self.__name)

# 静态字段
print(Foo.A)   # 共有在类外类里均可访问
#print(Foo.__A)
obj = Foo()    # 私有只能在类里访问
obj.aaa()

# 普通字段
print(obj.__name)  # 不能在外部访问
obj.aaa()  #  可在外部访问

obj1 = Bar()  #  执行父类的构造方法
print(obj.__name)  # 继承的子类在外部不能访问

obj1.fetch()  # 不能访问
obj1.aaa()    # 不能访问
  5.2 对于方法
class Foo:

    def __init__(self):
        pass

    def __aaa(self):
        print(‘aaa‘)

    def bbb(self):
        self.__aaa()

    @staticmethod
    def __eee():
        print(‘ddd‘)

    @staticmethod
    def fff():
        Foo.__eee()

# 普通方法
obj = Foo()
#obj.__aaa()  # 不能直接访问
obj.bbb()     # 间接访问

# 静态方法
# Foo.__eee() # 静态方法在外部通过类无法访问
Foo.fff()     # 间接访问私有的静态方法

# 类方法与特性均是一样的道理
  5.3 python与其他语言的区别之处,强行访问私有成员

    对象._类+私有成员

class Foo:

    def __init__(self):
        self.name = ‘alex‘
        self.__name = ‘wuwen‘

    def aaa(self):
        print(self.__name)

    def bbb(self):
        pass

obj = Foo()
# obj.__name  不能直接访问
print(obj._Foo__name)  # 强行访问
‘‘‘
wuwen
‘‘‘

  

6.类的特殊成员

  __init__

  __del__

  __call__

  __getitem__

  __setitem__

  __delitem__

  __new__

  __metaclass__

  6.1 对于字典的一些操作,由dict创建的对象为什么可以使用[ ],del等快捷键操作该对象

    __init__

    __getitem__

    __setitem__

    __delitem__

# dic = dict(k1=123, k2=456)  因为dic类中有__init__方法
# print(dic[‘k1‘])  为什么对象可以加[]呢  因为dic类中有__getitem__方法
# dic[‘k1‘] = 456   因为dic类中有__setitem__方法
# del dic[‘k2‘]     因为dic类中有__delitem__方法

class Foo:
    def __init__(self):
        print(‘init‘)

    def __call__(self, *args, **kwargs):
        print(‘call‘)

    def __getitem__(self, item):
        print(item)

    def __setitem__(self, key, value):
        print(key, value)

    def __delitem__(self, key):
        print(‘模拟删除成功!!‘)

obj = Foo()
obj()  # 对象后面加()执行__call__
obj[‘66‘]  # 对象后加[]执行__getitem__
obj[‘77‘] = 77
del obj[‘77‘]
‘‘‘
init
call
66
77 77
‘‘‘
  6.2 对于列表,他的切片操作又是如何在类中实现的呢?

    __getitem__

r = list([11, 22, 33, 44, 55, 66, 77])
ret = r[1:6:2]  # 切片
print(ret)

class Foo:
    def __getitem__(self, item):
        print(item, type(item))

obj = Foo()
obj()
obj[1:3]  # 切片的时候,将1:3传入一个slice类得到一个对象再传入getitem
‘‘‘
slice(1, 3, None) <class ‘slice‘>
‘‘‘
  6.3  __dict__
class Foo:
    ‘‘‘
    我是类的注释
    ‘‘‘

    def __init__(self):
        self.name = ‘alex‘
        self.gender = ‘female‘

    def __call__(self, *args, **kwargs):
        print(‘call‘)

    def __getitem__(self, item):
        print(item, type(item))

    def __setitem__(self, key, value):
        print(key, value)

    def __delitem__(self, key):
        print(‘模拟删除成功!!‘)

obj = Foo()
print(obj.__dict__)  # 查看对象封装的字段
‘‘‘
{‘name‘: ‘alex‘, ‘gender‘: ‘female‘}
‘‘‘
print(Foo.__dict__)  # 查看类的成员
‘‘‘
{‘__module__‘: ‘__main__‘, ‘__doc__‘: ‘\n    我是类的注释\n    ‘, ‘__init__‘: <function Foo.__init__ at 0x000000000220BA60>,
‘__call__‘: <function Foo.__call__ at 0x000000000220BAE8>, ‘__getitem__‘: <function Foo.__getitem__ at 0x000000000220BB70>,
‘__setitem__‘: <function Foo.__setitem__ at 0x000000000220BBF8>, ‘__delitem__‘: <function Foo.__delitem__ at 0x000000000220BC80>,
‘__dict__‘: <attribute ‘__dict__‘ of ‘Foo‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Foo‘ objects>}
‘‘‘
  6.4  类似于字符串,列表,为什么我们可以用for循环这个对象呢?

    事实上:如果for循环对象的时候,默认执行类中的__iter__方法,是一个生成器

    所以一个对象可以被for循环的话,说明这个对象的类中有__iter__ 方法

li = [1, 2, 3]  #  等价于 li = list([])
for i in li:
    print(i)
‘‘‘
1
2
3
‘‘‘

# 实现一个简单版本的list类
class Foo:

    def __iter__(self):
        yield 1
        yield 2
        yield 3

li = Foo()
for i in li:
    print(i)
‘‘‘
1
2
3
‘‘‘
  6.5 __new__和__metaclass__

        

时间: 2024-10-11 07:43:24

35.python全栈之路:面对对象进阶的相关文章

Python全栈--9.1--面向对象进阶-super 类对象成员--类属性- 私有属性 查找源码类对象步骤 类特殊成员 isinstance issubclass 异常处理

上一篇文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中) 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数 面向对象三大特性:封装.继承和多态 本篇将详细介绍Python 类的成员.成员修饰符.类的特殊成员. 注意点: self ,我们讲过了,self = 对象,实例化后的对象调用类的各种成员的时候的self就是这个对象. 而且我们也讲过了

Python全栈之路_01

Python全栈之路 前言:因为Python主要是在Linux和widows操作系统上使用所以,首先就介绍Pyhton在这两个平台上的安装和一些基础知识 Linux系统下安装Pyhton 1.工具 虚拟机:VMware workstation 12 Pro Linux系统:CentOS 64 位 VMware虚拟机安装很简单就不说明了. 在虚拟机安装CentOS 需要注意的是: 运行内存分配1G左右即可 可以开机按F2进入bios界面boot目录下选择启动设备选择Hard Drive为优先启动位

python 全栈之路

python 全栈之路 一. python 1. Python基础知识部分 Python Python那点事 Python windows和linux下 安装 Python2,Python3 Python 开启入坑之路 Python 基本数据类型 Python 那些零碎的知识点 Python -函数 Python - 面对对象 Python - 模块 Python - 文件操作 Python - python中经常踩得的坑 2. Python - 网络编程 3. Python - 并发编程 二.

Python全栈之路系列之赋值与运算符

Python全栈之路系列之赋值与运算符 在继续下面的文章之前我们先来浏览一下Python为我们提供的几种运算符,定义两个变量,分别是a和b,a的值是10,b的值是20. 算术运算符 运算符 描述 实例 + 加,两个对象相加 a+b=30 - 减,两个对象相减,可能会得到负数 a-b=-10 * 乘,两数相称或是返回一个被重复若干次的字符串 a*b=200 / 除,两个对象相除 b/a=2 % 取膜,返回除法的余数 b%a=0 ** 幂,返回x的y次幂 a**b=10000000000000000

Python全栈之路----常用模块----hashlib加密模块

加密算法介绍 HASH       Python全栈之路----hash函数 Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值. 简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数. HASH主要用于信息安全领域中加密算法,他把一

Python全栈之路----函数----返回值

函数外部的代码想要获取函数的执行结果,就可以在函数里用return语句,把结果返回. def stu_register(name,age,course='PY',country='CN'): print('----注册学生信息----') print('姓名:',name) print('年龄:',age) print('国籍:',country) print('课程:',course) if age > 22: return False else: return True registriat

Python全栈之路系列----之-----面向对象4接口与抽象,多继承与多态)

接口类与抽像类 在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念 编程思想 归一化设计: 1.接口类 不实现具体的方法,并且可以多继承 2.抽象类 可以做一些基础实现,并且不推荐多继承 编程的几类原则: 开放封闭原则:对扩展示开放的,对修改是封闭的依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该应该依赖细节:细节应该依赖抽象.换言之,要针对接口编程,而不是针对实现编程接口隔离原则:使用多个专门的接口,而不使用单一的总接口.

Python全栈之路系列----之-----re模块(正则表达式)

正则表达式并不是python中的一部分,正则表达式适用于处理字符串的强大工具,拥有自己独特的语法,以及独立的处理引擎.在提供了正则表达式的语言中都它的语法是都一样的 re模块本质上和正则表达式没有一毛钱的关系,re模块是python提供给我们方便操作正则的工具而已 正则表达式概念 使用单个字符串规则来描述匹配一系列符合某个句法规则的字符串 是对字符串操作的一种逻辑公式 应用场景:处理文本和数据 正则表示是过程:依次拿出表达式和文本中的字符比较,如果每一个字符都能匹配,则匹配成功:否则匹配失败 正

Python全栈之路---运算符与基本的数据结构

运算符 一.算术运算符: 练习: + 加法 两个对象相加 1 + 2得到3:'a' + 'b'得到'ab'. - 减法 一个数减去另一个数或者是负数 5 - 3得到2:-2得到一个负数 * 乘法 两个数相乘或者返回一个被重复若干次的字符串 -5.2得到一个负数.50 - 24得到26. ** 幂 返回x的y次幂 3 ** 4得到81(即3 * 3 * 3 * 3) / 除 x除以y 4/3得到1(整数的除法得到整数结果).4.0/3或4/3.0得到1.3333333333333333 // 取整