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