Python进阶
Python一切皆对象
对象介绍
Python的对象是一种数据抽象或者数据结构抽象,对象应该同时具备:本征值(Indentity)、型式(Type)、值(Value)三个参数。
a = 45 print(id(a)) # 表示在python中的唯一内存地址,具备唯一性 print(type(a)) print(a) /*-----output-------*/ 2063144480432 <class 'int'> 45
对象具体指变量Variable、类Class、函数Function,具备四种用途:
- 作为返回值
- 赋值给另一个对象
- 作为函数参数传递
- 添加到另一个集合对象
Object、Class、Type关系
type可以用于查看对象,创建对象
a = 45 print(type(a)) print(type(type(a))) print(type.__bases__) print(type(type)) /*-----output-------*/ <class 'int'> # a由int创建 <class 'type'> # int由type创建 (<class 'object'>,) # type继承object <class 'type'> # type自己创建自己
class声明一个类
class STU: pass stu = STU() print(type(stu)) print(type(STU)) /*-----output-------*/ <class '__main__.STU'> # stu的实例化由STU完成 <class 'type'> # STU类由type创建
object是所有class的基类
class STU: pass print(STU.__bases__) /*-----output-------*/ (<class 'object'>,) # STU继承自object类
1、所有的class都继承自object,所有的class都由type创建
2、type本身也是class,因此type自身创建了自身
3、python中一切皆对象,因为所有对象都由type创建,包括type类本身
Python的内置类型
None:本身也是一个对象,全局只有一个
数值:int,float,complex(复数),bool
迭代类型:迭代器和生成器
序列类型:list、bytes、bytearray、memoryview(二进制)、tuple、str、array
映射:dict
集合:set、frozenset(不可变)
上下文管理:with(文件管理)
其他:模块类型(import)、class、函数类型、方法类型、代码类型、type类型、object类型、ellipsis类型、notimplemented类型
所有的对象都有类型
类
类变量与实例变量
类变量是所有相关类实例共用的变量,只能通过类去修改类变量。通过类实例修改类变量时将会新建一个实例变量,无法修改类变量。
class A: # 类变量 character = 0 def __init__(self,x): self.x = x # 实例变量 a = A(2) # 可以通过类实例访问类变量忽然实例变量 print(a.x,a.character) # 可以通过类访问类变量,但不能访问实例变量 print(A.character) # 实例对象修改类变量时会重新创建一个对应的实例变量! a.character = 5 print(a.character) A.character = 3 print(a.character) # a.character = 5
私有变量
私有属性是类的一种私密变量,通过变量前加双下划线__
。私有属性不能被继承,私有属性不可以作为返回值。
class Date: def __init__(self, year, month, day): # 实例属性 self.year = year self.month = month self.day = day class User: def __init__(self,birthday): # 私有属性:具体日期是涉密的 self.__birthday = birthday # 私有属性只能在类方法中直接使用,无法通过结成,无法作为返回值 def age_get(self): year = self.__birthday.year # 只能间接返回,不建议将私有属性开放给外部访问 return 2024 - year if __name__ == '__main__': user = User(Date(1990,4,24)) print(user.age_get())
类方法
类方法:传入cls,装饰器为classmethod。
静态方法:传入self类实例,装饰器为staticmethod。硬编码。
实例方法:传入self类实例。
class Date: def __init__(self, year, month, day): # 实例属性 self.year = year self.month = month self.day = day # 实例方法:带有self参数,self是当前类的实例对象 def __str__(self): return F"{self.year}/{self.month}/{self.day}" # 静态方法:不需要添加self实例对象,实例都可以调用 @staticmethod def DataTransfer(DataStr): y,m,d = tuple(DataStr.split('-')) return Date(y,m,d) # 硬编码,如果类名更改,方法就会出错 # 类方法:添加cls,指向类 @classmethod def DataTransferCls(cls,DataStr): y,m,d = tuple(DataStr.split('-')) return cls(y,m,d) if __name__ == "__main__": newday = Date(2024,1,8) print(newday) newday1 = Date.DataTransfer("2024-01-25") print(newday1) newday2 = Date.DataTransferCls("2024-08-03") print(newday2)
魔术方法
魔术方法是类中固有功能的拓展。以__
双下划线开头。
from abc import abstractmethod, ABCMeta class Student: def __init__(self, StuList): self.StudentList = StuList # 魔法函数:枚举 def __getitem__(self, item): return self.StudentList[item] # 魔法函数:成员长度 def __len__(self): return len(self.StudentList) stu = Student(['jim', 'tom', 'eason']) # 常规遍历 for item in stu.StudentList: print(item) # 魔术方法遍历 for item in stu: print(item) # 魔法方法求指定成员长度 print(len(stu))
__len__方法
len()方法会调用__len__,当统计的是Python的内部方法时,会直接调用C语言库,速度很快。
方法重写
子类重写父类的方法
class Animal: def say(self): print("i'm animal") class Dog(Animal): def say(self): # 重写 print("i'm a dog") class Duck(Animal): def say(self): # 重写 print("i'm a duck")
鸭子类型
多个类的方法名一致,将其存入列表进行迭代调用就可以实现类似多态的功能。这些类可以统称为鸭子类型。
class Dog(): def say(self): print("i'm a dog") class Duck(): def say(self): print("i'm a duck") dog = Dog() duck = Duck() animal = [dog,duck] for an in animal: an.say()
抽象基类
抽象基类的设计非常考验框架开发的功力,常规开发中仅使用多继承。
from abc import ABCMeta,abstractmethod class AbstractClass(metaclass=ABCMeta): @abstractmethod def kind(self): pass @abstractmethod def name(self): pass class HistoryBook(AbstractClass): def __init__(self): pass def kind(self): pass def name(self): pass hb = HistoryBook()
类型判断isinstance
类型读取是type()
,类型判断使用isinstance()
pass class B(A): pass a = A() b = B() print(isinstance(a,B)) # 父类实例是不是和子类一致 false print(isinstance(b,A)) # 子类实例是不是和父类一致 true print(type(a) is B) # 父类实例是不是和子类一致 flase print(type(b) is A) # 子类实例是不是和父类一致 true a = 12 print(isinstance(a,int)) # 判断常量是否为int true print(type(a) is int)
Super()
super函数并不是调用父类的函数,而是继承的父类中优先级最高的类。
class A: def __init__(self): print('A') class B(A): def __init__(self): print('B') super().__init__() # 调用__init__,调用顺序是按类的继承顺序来调用的 class C(A): def __init__(self): print('C') super().__init__() # 调用__init__,调用顺序是按类的继承顺序来调用的 class D(C,B): def __init__(self): print('D') super().__init__() # 调用__init__,调用顺序是按类的继承顺序来调用的 d = D() print(D.__mro__) # 打印类的继承优先顺序
Python的自省机制
编程语言中的自省机制是指知道一个变量叫什么?有什么用途。例如__dict_、dir()、_isinstance()、type()
等。高级的自省则是反射hasattr()、getattr()、setattr()、delattr()
。可以使用字符串去指向整个对象,达到怎么用?。
class Person: name = 'user' class Student(Person): def __init__(self,fullname): self.fullname = fullname user = Student("lucy") # 通过__dict__查询属性:实例中所有的变量与值组成的字典 print(user.__dict__) # dir会列出对象的所有可用属性 print(dir(user))
With与上下文管理器
with上下文管理器中可以使用满足上下文协议的语句
__enter__\__exit__
# with上下文管理器语句就是为了简化 try finally的写法 class Sample: def __enter__(self): # enter里面去获取资源 print("enter") return self # 必须存在返回值 def __exit__(self, exc_type, exc_val, exc_tb): # exit中去释放资源 print("exit") def do_something(self): # 操作资源 print("donging something!") with Sample() as sam: sam.do_something() # 离开with语句的时候会自动调用__exit__
contextlib
import contextlib @contextlib.contextmanager def Fileopen(filename): # yield之前进行前置处理 print("File Open.") # 做一些操作 yield {} # 生成一个空字典,contextmanager必须包含生成器 # yield之后进行后续处理 print("File End") with Fileopen("boby.txt") as f: print("file processing.")
is与==
==
用于检查对象值
is
用于检查对象值和内存地址是否相同,是更严格的==
a = [1,2,3] b = [1,2,3] print(id(a),id(b)) # 3046412739008 3046412738688 print(a == b) # true 仅检查值 print(a is b) # false 检查值与内存位置 c = 1 d = 1 print(id(c),id(d)) # 3046407498032 3046407498032 print(c == d) # true print(c is d) # true python中将一定范围内得小整数会自动进行整合
推导式
推导式就是一行代码生成对应的数据类型。
列表推导式
也称列表生成式,列表生成式高于列表操作
# 生成20以内的奇数 odd_list = [i for i in range(21) if i % 2 ==1] print(odd_list) # 复杂情况:引入函数 def handle(i): return i*i odds_list = [handle(i) for i in range(21) if i % 2 ==1] print(odds_list)
生成器表达式
将列表推导式的[]换为(),生成器表达式可以通过转换及迭代来访问。
list1 = (i for i in range(21) if i % 2 ==1) # []变成()会变成生成器 print(list1) print(list(list1))
字典推导式
# 字典推导式 dict1 = {"tom1":22,"tom2":33,"tom3":44} print(dict1) reverse_dict = {value:key for key,value in dict1.items()} # 颠倒键值 print(reverse_dict)
集合推导式
# 集合推导式 dict1 = {"tom1":22,"tom2":33,"tom3":44} set1 = {key for key,value in dict1.items()} print(set1)
Bisect序列查找
Bisect用于维护已经排序好的序列,主要有insort_right\bisect_right\insort_left\bisect_left
四种方法
import bisect li = [1,2,3,4,5,7] index4 = bisect.bisect_left(li,4) # 返回一个新列表 print('{} 左插 {}'.format(li,index4)) index5 = bisect.bisect_right(li,4) print('{} 右插 {}'.format(li,index5))
Dict字典
userdict、dict、defaultdict的区别
userdict
是python开放给用户用于重新定义字典数据操作的类,可以进行方法覆盖等各种定义行为
dict
是python默认的dict
类,任何dict
的定义都是dict
进行实例化
defaudict
是dict的子类,只是新增了missing
方法和一个default_factory
重新定义dict行为时继承userdict
,不可以继承dict
,因为继承dict
只适用添加新方法,如果对dict
原有的魔法函数进行覆盖将无效
垃圾回收机制
python中的垃圾回收采用 引用计数为主,隔代回收为辅的策略
引用计数:类似于C++的智能指针shared_fur
a = 1 # 计数器=1 b = a # 计数器=2 del a # 计数器 = 2-1 python中delete并不是回收,此时仍然有值,只有引用计数器 = 0时才会回收b
隔代回收:当交叉引用时,会先回收引用的对象
class A: def __init__(self): self.pro = None def __del__(self): # 垃圾回收 print("回收A") class B: def __init__(self): self.pro = None def __del__(self): # 垃圾回收 print("回收B") classA = A() classB = B() classA.pro = classB classB.pro = classA del classA # 先回收B
元类编程
Setter与Getter
class User: def __init__(self, name): self.name = name self._name = None def getname(self): return self.name # 直接作为一种属性 @property # 在python中的getter方法使用@property修饰 def gname(self): return self.name @gname.setter def sname(self,value): self.name = value if __name__ == "__main__": user = User('zhang075') print(user.gname,user.name) user.sname = "zhang" # setter print(user.gname,user.name)
__getattr__与__getattribute__
class User: def __init__(self,info = {}): self.info = info # 查找不到时会进入此函数 def __getattr__(self, item): return '属性不存在' # 属性拦截器 def __getattribute__(self, item): print('开始属性拦截') return super().__getattribute__(item) # 返回属性值,如果不存在会调用__getattr__ us = User(info = {'name':'zhangwei','age':'15'}) print(us.info['name'])
属性描述符
描述符的作用是用来代理另外一个类的属性(必须把描述符定义成这个类的类属性,不能定义到构造函数中),属性描述符可以对类对象进行检查
import numbers class IntField: def __get__(self, instance, owner): # 属性描述符,本质就是魔法函数 return self.value def __set__(self, instance, value): if isinstance(value,numbers.Integral): print('%d 类型检查通过' % value) else: raise ValueError("类型检查不通过") self.value = value # 存放值 def __delete__(self, instance): del self.value class NonDataIntField: def __get__(self, instance, owner): # 非数据描述符 return self.value class User: age = IntField() #age是属性描述符得对象,类对象
描述符具备优先级:
1>类属性
2>数据描述符
3>实例属性
4>非数据描述符
5>找不到的属性触发__getattr__()
本文来自博客园,作者:{张一默},转载请注明原文链接:https://www.cnblogs.com/YiMo9929/p/17931512.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)