Python进阶----类的结构(公有成员 , 私有成员(私有属性,私有方法),类方法,静态方法,属性) ,isinstance 和issubcalss ,元类(type())
Python进阶----类的结构(公有成员 , 私有成员(私有属性,私有方法),类方法,静态方法,属性) ,isinstance 和issubcalss ,元类(type())
一丶类的结构细分
成员:
公有属性(静态属性,对象属性),私有属性(私有静态属性,私有对象属性),私有方法,公有方法,类方法,静态方法,属性.代码如下:👇
#### 整合版
class A:
public_attr = '公共属性' # 公有属性(静态变量)
__private_attr = '私有属性' # 私有属性(私有静态变量)
def __init__(self, name, sex): # 初始化方法
self.name = name # 实例化对象时 公有属性
self.__sex = sex # 实例化对象时 私有属性
def func(self): # 公有方法(实例化方法,默认将调用者对象传给self)
print('in A 类 公有方法')
def __func2(self): # 私有方法
print('in A 类 私有方法')
### 👇以下的这些 类方法, 静态方法,属性 . 只存在于类空间,不存在对象空间
@classmethod # 类方法
def func3(cls): # cls是一个参数,默认传递当前类的类名
obj=cls() # 实例化一个对象, 因为cls是一个类的内存地址
print('类方法')
@staticmethod # 静态方法
def func4(): # 默认不需要传参(根据需要,也可以传参),
print('静态方法')
@property # 属性(将一个函数伪装成一个类成员属性,只存在于类空间)
def func5(self):
return 1+1
# 测试
def func6(self):
#私有属性
print(A.__private_attr) # 类 只能在类的内部使用类的私有属性 ,
print(self.__sex) # 对象 只能在类的内部使用对象的私有属性
print(self.__private_attr) # 对象 只能在类的内部使用对象的私有属性
# 私有方法
self.__func2() # 对象 只能在类的内部使用私有方法
A.__func2('a') # 类 只能在类的内部使用私有方法
print(A.__dict__) # 查看当前的A类中有哪些属性和方法(变量与值的对应关系)
### 类的公有静态属性,类的外部,类的内部, 派生类都可以访问
obj_a=A('李四','男') #实例化对象
print(A.public_attr)
print(obj_a.public_attr)
### 本类的私有属性 ,只能在 类的内部使用类的私有属性,类的外部不能使用类的私有属性
print(A.__private_attr) # AttributeError: type object 'A' has no attribute '__private_attr'
A.func6('a') # 只能在类中使用私有属性
### 对象的私有属性,只能在类的内部使用对象私有属性,或者类的私有属性,类的外部不能使用对象私有属性,或者类的私有属性,
obj_a=A('李四','男') #实例化对象
print(obj_a.__sex) # AttributeError: 'A' object has no attribute '__sex'
obj_a.func6() # 只能在类的内部使用私有属性(对象既可以使用对象私有属性,也可以使用类的私有属性 )
### 私有方法 只能在类的内部使用,不能再类的外部使用
obj_a=A('李四','男')
obj_a.__func2() # 在类的外部 对象不能调用类中的私有方法
A.__func2() # 在类的外部 类不能调用类中的私有方法
obj_a.func6() # 只能在类中调用私有方法
### 总结 :
# 对于 类的公有静态属性,类的外部,类的内部, 派生类都可以访问
# 对于 类的私有静态属性,只能在类的内部使用.派生类都不可以访问
拓展:
# # 如果想设定一些私有的,或者是不想让类外面用到 如: 密码,加密方式
# # 拓展: 私有成员除了在内部,当真访问不到吗? , ( 不要使用)
class A:
__girl='123'
# python 中所有的私有成员: 就是在私有成员前面上 _类名而已
print(A._A__girl) # 可以访问类成员中的私有属性
# # python 默认对私有属性的加密方式就是在 类前面加了一个_
# print(A.__dict__) 可以查看这个类的全部属性
二丶私有方法,私有属性
作用:
一些私密的方法,或私密的属性不能被查看:如(加密方法,女生的体重属性)
class A:
public_attr = '公共属性' # 公有属性(静态变量)
__private_attr = '私有属性' # 私有属性(私有静态变量)
def __init__(self, name, sex): # 初始化方法
self.name = name # 实例化对象时 公有属性
self.__sex = sex # 实例化对象时 私有属性
def func(self): # 公有方法
print('in A 类 公有方法')
def __func2(self): # 私有方法
print('in A 类 私有方法')
# 测试
def func6(self):
# 私有属性
print(A.__private_attr) # 类 只能在类的内部使用类的私有属性 ,
print(self.__sex) # 对象 只能在类的内部使用对象的私有属性
print(self.__private_attr) # 对象 只能在类的内部使用对象的私有属性
# 私有方法
self.__func2() # 对象 只能在类的内部使用私有方法
A.__func2('a') # 类 只能在类的内部使用私有方法
print(A.__dict__) # 查看当前的A类中有哪些属性和方法(变量与值的对应关系)
### 对于 类的公有静态属性,类的外部,类的内部, 派生类都可以访问
obj_a=A('李四','男') #实例化对象
print(A.public_attr)
print(obj_a.public_attr)
### 本类的私有属性 ,只能在 类的内部使用类的私有属性,类的外部不能使用类的私有属性
print(A.__private_attr) # AttributeError: type object 'A' has no attribute '__private_attr'
A.func6('a') # 只能在类中使用私有属性
### 对象的私有属性 只能在类的内部使用对象私有属性,或者类的私有属性,类的外部不能使用对象私有属性,或者类的私有属性,
obj_a=A('李四','男') #实例化对象
print(obj_a.__sex) # AttributeError: 'A' object has no attribute '__sex'
obj_a.func6() # 只能在类的内部使用私有属性(对象既可以使用对象私有属性,也可以使用类的私有属性 )
### 私有方法 只能在类的内部使用,不能再类的外部使用
obj_a=A('李四','男')
obj_a.__func2() # 在类的外部 对象不能调用类中的私有方法
A.__func2() # 在类的外部 类不能调用类中的私有方法
obj_a.func6() # 只能在类中调用私有方法
三丶类方法
作用:
@classmethod装饰 ,由类名直接调用的方法,通过它来传递类的属性和方法(不能传实例的属性和方法)
class B:
@classmethod
def func3(cls): # 谁调用 ,cls 接收的就那个对象的从属类
print(cls)
class A(B): # A类 继承B类
num=1
def __init__(self):通过它来传递类的属性和方法(不能传实例的属性和方法);
pass
def func2(self):
print('这是实例方法')
@classmethod # 类方法: 由类名直接调用的方法, 她会自动的将类名传给cls
def func(cls):
print(cls) # 这是类名 <class '__main__.A'>
print(cls.num) # 调用传递类中的属性 num=1
o=cls() # cls接收的是A类的内存地址, 类+()生成一个对象
print(o) # <__main__.A object at 0x000002BD6EA54518>
print('这是类方法')
print(A)
A.func() # 类调用类方法 , 默认将类名传给了cls
obj=A() # 实例化对象
obj.func() # 对象也可以调用类方法, 但是会自动将其从属于的类名传给cls
obj.func3() # <class '__main__.A'> # 同理,调用父类的类方法,自动将当前的对象从属的类传给cls
### 总结:
# 类方法使用装饰器@classmethod. 第一个参数必须传递当前类对象(类的内存地址),该参数名约定'cls'
# 通过它来传递类的属性和方法(不能传实例的属性和方法);
#调用:实例对象和类对象都可以调用。
例题:
定义一个Student类, 我要统计学生的个数
class Student:
num=0
def __init__(self,name):
self.name=name
self.count_stu() # 调用 类方法 进行统计,实例化一次对象,调用一次
@classmethod # 定义类方法, 用于统计
def count_stu(cls):
cls.num+=1
@classmethod # 定义类方法,用于返回结果
def result(cls):
return cls.num
s1=Student('da')
s2=Student('da1')
s3=Student('da2')
s4=Student('da3')
print(Student.num) # 调用类的num属性4
print(Student.result()) # 调用类方法,返回结果 4
四丶静态方法
作用:
使用装饰器@staticmethod,不依赖类, 也不依赖于对象, 静态方法是个独立的、单纯的函数 , 使结构更加清晰和合理
class A:
def __init__(self):
pass
@staticmethod # 类 和 对象 都能调用
def static_func(a,b,c):
print(f'{a}{b}{c}这是一个静态方法')
### 对象和类 都能调用静态方法
A.static_func(1,2,3) # 类调用 静态方法
obj=A()
obj.static_func(1,2,3) # 对象 调用静态方法
### 总结:
# 使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;
#调用:实例对象和类对象都可以调用。
例题:
### 获取当前时间的函数。
import time
class TimeTest(object):
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second
@staticmethod
def showTime():
return time.strftime("%H:%M:%S", time.localtime())
print(TimeTest.showTime())
t = TimeTest(2, 10, 10)
nowTime = t.showTime()
print(nowTime)
五丶属性(特殊)
作用:
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值*
将一个类的函数定义成属性后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
一个静态属性property本质就是实现了get,set,delete三种方法
###### 方式 一
class Foo:
@property
def aaa(self):
print('get的时候用到')
return 'aaa'
@aaa.setter # 当修改property伪装成的属性的属性值,aaa.setter装饰此函数.自动调用
def aaa(self,value): # 函数名必须和原定义的函数名一直.
print(value) # value 接收的要修改的属性值()
print('set 修改的时用到')
@aaa.deleter
def aaa(self):
print('delete 删除的时候用到')
f1=Foo()
f1.aaa #调用这个aaa伪装属性函数 get的时候用到
f1.aaa='AAA' # 并不会在对象空间创建一个新的属性. 这是一个存在类中的伪装成属性的函数,
# 修改时,相当于是修改类空间中存在的这个伪装属性函数的值
print(Foo.__dict__) # 'aaa': <property object at 0x000001F9D9C76958>
del f1.aaa # 删除
# 结果:
get的时候运行到我
set的时候运行到我
delete的时候运行到我
###### 方式 二
class Foo:
def get_AAA(self):
print('get的时候运行我啊')
def set_AAA(self,value):
print('set的时候运行我啊')
def delete_AAA(self):
print('delete的时候运行我啊')
AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
### 调用:实例对象和类对象都可以调用。
六丶isinstance issubcalss
isinstance(obj,M):
判断obj对象 是否是M类,(或者M类的子类)实例化出的对象
### 判断obj对象 是否是M类,(或者M类的子类)实例化出的对象
class A:
pass
class B(A):
pass
class C(B):
pass
obj = B()
print(isinstance(obj,B)) # 判断obj对象 是不是 B类或B类的子类实例化的对象
print(isinstance(obj,A)) # 判断obj对象 是不是 A类或A类的子类实例化对象
print(isinstance(obj,object)) # 判断 obj 是不是 object类 或object的子类实例化对象
print(isinstance(obj,C)) # C类不是B 的子类 False ?????
issubcalss(M,N):
判断 M类 是不是从属于 N 类 或N类的子类(派生类)
### 判断 M类 是不是从属于 N 类 或N类的子类
class A:
pass
class B(A):
pass
class C(B):
pass
class D(C):
pass
print(issubclass(B,A)) # 判断 B类 是不是从属于 A 类 或A类的派生类
print(issubclass(C,A)) # 判断 C类 是不是从属于 A 类 或A类的派生类
print(issubclass(C,object)) # 判断 C类 是不是从属于 object 类 或object类的派生类
print(issubclass(C,D)) # 判断 C类 是不是从属于D 类 或D类的派生类False
七丶元类type(name, bases, dict)
元类: 就是能够实例化所有类包括object类, 同时还继承object类,(有待深入研究)
name -- 类的名称。
bases -- 基类的元组。
dict -- 字典,类内定义的命名空间变量。
type元类是获取该对象从属于的类,而type类比较特殊,Python原则是:一切皆对象,其实类也可以理解为'对象',而type元类又称作构建类,python中大多数内置的类(包括object)以及自己定义的类,都是由type元类创造的。
而type类与object类之间的关系比较独特:object是type类的实例,而type类是object类的子类,这种关系比较神奇无法使用python的代码表述,因为定义其中一个之前另一个必须存在。所以这个只作为了解。
## 案例一:
from collections import Iterable
from collections import Iterator
s1='absad'
str()
print(type(s1)) # 判断的是对象从属于哪个类
# type 也叫元类 , 一切皆对象. 一个类也是一个对象, 那么这个(类)对象肯定是由类实例化出来的
# 在python中你创建的所有类, 以及大部分list str 等等这些类,都是从type元类实例化来的
## 案例二:
print(type('abc'))
print(type(True))
print(type(100))
print(type([1, 2, 3]))
print(type({'name': '太白金星'}))
print(type((1,2,3)))
print(type(object))
class A:
pass
print(isinstance(object,type))
print(isinstance(A, type))