Python高级知识点学习(三)

简介:

mro算法

类属性和实例属性的查找顺序

  • 何为类属性:定义在类内部的的一些变量或者方法,都统称为类属性
  • 何为实例属性:定义在对象内部的的一些变量或者方法,都统称为实例属性

对象也就是实例的意思。

class A:
    aa = 1
    def __init__(self, x, y):
        self.x = x
        self.y = y
a = A(2, 3)

类也是对象,看上边代码,实际上有两个空间,A 和 a 两个不同的空间。
单继承时,属性查找方式,向上查找,首先查找对象里,再查找类中

在多继承时,会很复杂

python2.2之前,python里的类叫经典类,经典类继承方式如果不显式继承object,实际上是不会自动继承object,Python3中,经典类已经不存在了,都叫做新式类。
经典类中,深度优先查找 。

Python2.3之后,广度优先也没有了,至今都采用C3算法
Python3多重继承C3算法:

#新式类
class D:
    pass

class E:
    pass

class C(E):
    pass

class B(D):
    pass

class A(B, C):
    pass

print(A.__mro__)

打印结果:
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)
可以看到继承顺序是 A - B - D - C - E - object

类方法静态方法和实例方法

实例方法:实例方法很常见,通常我们在类里定义的都是实例方法,

  • 只是针对于实例进行操作,实例方法中第一个参数:self,self代表的就是实例本身

静待方法:

  • 带@staticmethod装饰器的方法叫静态方法,静态方法不需要接受cls或self,和普通的函数用法一样

类方法:

  • 带@classmethod装饰器的方法叫做类方法,类方法第一个参数是cls,代表的是类本身,(这里的cls可以修改为任意形式的代表)
    def a(self):
        pass
    
    @staticmethod
    def b():
        pass
    
    @classmethod
    def c(cls):
        pass

Python中的私有属性

双下划綫开头表示私有属性,私有属性的访问,只能在类中的公共方法中访问,类外部防问不到,无法通过实例访问。

私有属性不仅仅是变量 还可以是函数。

class User:
    def __init__(self, birthday):
        self.__birthday = birthday

user = User(2000)
print(user.birthday)

运行结果:
AttributeError: 'User' object has no attribute 'birthday'

以上代码块结果就是访问不到私有属性。

但是,私有不是绝对的,只是加了一个小技巧,Python中将私有属性的访问变形成这种:

class User:
    def __init__(self, birthday):
        self.__birthday = birthday
    

user = User(2000)
print(user._User__birthday)

运行结果:
2000

可以看到,通过变量_User__birthday这个就可以访问到私有属性。

Java中的反射机制也是无法做到绝对安全的,从语言层面讲,没有绝对的私有属性,Python简单一些 Java麻烦一些。

Python自省

Python对象自省
何为自省?
自省是通过一定的机制查询到对象的内部结构
使用__dict__魔法函数,dict是用C语言写的 性能高,做了很多优化,推荐使用。

也可以使用dir() ,dir()会列出类中所有属性,推荐使用。

class Student():
    def __init__(self, scool_name):
        self.scool_name = scool_name


if __name__ == "__main__":
    user = Student("zhao")

    #通过__dict__查询属性
    print(user.__dict__)

打印结果:
{'scool_name': 'zhao'}
class Student():
    def __init__(self, name):
        self.name = name


if __name__ == "__main__":
    user = Student("zhao")
    user.__dict__["school_addr"] = "北京市"
    print(user.school_addr)
    print(user.name)
    a = [1, 2]
    print(dir(a))
    print(dir(user))

打印结果:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'school_addr', 'scool_name']
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

Python中super()函数

super()就是调用父类。

class A:
    def __init__(self):
        print('is A')

class B(A):
    def __init__(self):
        print('is B')
        # 在某些情况下,我们希望在运行完以上代码调用父类的init方法,一般在Python3中使用下面这种方法调用
        super().__init__()

if __name__ == "__main__":
    b = B()

打印结果:
is B
is A

super()就是调用父类,其实这样讲并不准确,super()函数调用其实是按照mro查找的顺序调用的。

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


class B(A):
    def __init__(self):
        print("B")
        super().__init__()


class C(A):
    def __init__(self):
        print("C")
        super().__init__()


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


if __name__ == "__main__":
    print(D.__mro__)
    d = D()

打印结果:
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
D
B
C
A

既然我们重写子类的构造函数, 为什么还要去调用super再次调用父类构造函数?
有些时候,为了使用父类中的一些已经写好的方法,所以会有使用super的情况。

上下文管理器

首先介绍下这种用法:

try:
    print("code started")
    raise KeyError
    return 1
except KeyError as e:
    print ("key error")
    return 2
else:
    print("other error")
    return 3
finally:
    print ("finally")
    return 4

result = exe_try()
print (result)

运行结果:
code started
key error
finally
4

在finally语句块中的代码,不管上边代码是否发生异常都会执行finally中的代码,优先finally中的return,其次return上边的。

上下文管理器,也就是with语句,实质上就是为了解放try finally这种写法而诞生的。

上下文管理器是如何完成的呢?
python是基于协议进行编程的,上下文管理器就是一种协议:上下文管理器协议。

上下文管理器协议可以使用是因为实现了两个魔法函数:
__enter____exit__

class Sample:
    def __enter__(self):
        print("enter")
        # 获取资源
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        # 释放资源
        print("exit")

    def do_something(self):
        print("doing something")


with Sample() as sample:
    sample.do_something()

运行结果:
enter
doing something
exit

还有一种方法,可以简便的实现上下文管理器的功能:
@contextlib.contextmanager 可以将一个函数变为上下文管理器

import contextlib

@contextlib.contextmanager
def file_open(file_name):
    print ("file open")
    yield {}
    print ("file end")

with file_open("a.txt") as f_opened:
    print("file processing")

运行结果:
file open
file processing
file end

@contextlib.contextmanager内部会做一些逻辑,其实是利用了生成器的特性。

目录
相关文章
|
15天前
|
Python
python函数的参数学习
学习Python函数参数涉及五个方面:1) 位置参数按顺序传递,如`func(1, 2, 3)`;2) 关键字参数通过名称传值,如`func(a=1, b=2, c=3)`;3) 默认参数设定默认值,如`func(a, b, c=0)`;4) 可变参数用*和**接收任意数量的位置和关键字参数,如`func(1, 2, 3, a=4, b=5, c=6)`;5) 参数组合结合不同类型的参数,如`func(1, 2, 3, a=4, b=5, c=6)`。
16 1
|
11天前
|
Python
python学习3-选择结构、bool值、pass语句
python学习3-选择结构、bool值、pass语句
|
1天前
|
运维 Shell Python
Shell和Python学习教程总结
Shell和Python学习教程总结
|
2天前
|
Python
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
|
2天前
|
开发框架 前端开发 数据库
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
|
2天前
|
数据采集 数据可视化 数据处理
Python从入门到精通的文章3.3.1 深入学习Python库和框架:数据处理与可视化的利器
Python从入门到精通的文章3.3.1 深入学习Python库和框架:数据处理与可视化的利器
|
2天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
6天前
|
数据可视化 Python
Python模型评估与选择:面试必备知识点
【4月更文挑战第17天】本文深入探讨了Python模型评估与选择在面试中的关键点,包括性能度量、过拟合与欠拟合识别、模型比较与选择、模型融合和偏差-方差权衡。强调了避免混淆评估指标、忽视模型验证和盲目追求高复杂度模型的常见错误,并提供相关代码示例,如交叉验证、网格搜索和超参数调优。通过理解这些概念和技巧,可在面试中展示出色的数据科学能力。
31 12
|
9天前
|
机器学习/深度学习 算法 Python
使用Python实现集成学习算法:Bagging与Boosting
使用Python实现集成学习算法:Bagging与Boosting
18 0
|
10天前
|
Python
python学习-函数模块,数据结构,字符串和列表(下)
python学习-函数模块,数据结构,字符串和列表
49 0