上篇文章,我们对类,实例,属性,方法有了一个初步的了解。会书写创建,访问相关的属性方法,也深入理解了self的含义,这篇文章,我们要更深入的探讨属性和方法。
这篇文章里,很多内容都是一通百通的,前期可能内容量大一点,后面就只是相同概念在不同情况下的简单变形
1.属性的分类:
我们可以将属性分为以下三类:
(1)实例属性:
就是我们在之前写的,在 __init__ 方法中定义的属性。运用广泛,但没啥好说的。
class PeoplePeople:
def __init__(self, gender):
self.gender = gender # 实例属性
(2)私有属性:
私有属性是那些不应该在类的外部直接访问的属性。
以双下划线 __ ,单下划线 _ 开头。(这是程序员之间的约定)但双下划线的安全性要大于单下划线。
安全性?因为在python里,对私有属性的保护,即避免外部访问类的私有属性,很不严格。只要开发人员不自觉,外部是可以访问私有属性的。
class PeoplePeople:
def __init__(self, tall, age):
self.gender = gender # 实例属性
self._tall = gender # 双下下划线私有属性
self.__age = age # 单下下划线私有属性
运行一下:
you = PeoplePeople("男",180,18)
print(you.gender)
print(you._tall)
print(you.__age)
#结果:
男
180
AttributeError: 'PeoplePeople' object has no attribute '__age'
可以看到,单下划线_tall的根本就没什么保护,直接就访问了,只靠自己自觉了
双下划线我们可以进行强制访问:
print(you._PeoplePeople__age)
实例._类名__属性名
18
但是吧,他们都是私有变量,你把他们都定义成私有变量了,还为什么非要外部访问呢。。。
(3)类属性:
类属性是与类本身相关的属性,所有实例共享同一个类属性。
在类定义中直接定义,而不是在 __init__ 方法中。
class PeoplePeople:
country = "china" # 类属性
def __init__(self, gender):
self.gender = gender # 实例属性
每个实例都可以访问的,跟实例属性差不多,只不过是公共的
2.对属性进行操作:
class PeoplePeople:
country = "china" # 类属性
def __init__(self, gender, tall,age):
self.gender = gender # 实例属性
self._tall = tall # 双下下划线私有属性
self.__age = age # 单下下划线私有属性
(增)如果有些属性不方便直接初始化,我们可以采取动态添加,说白了就是在运行时加上的属性。经过我们前面学的,能进行此操作的就有类属性,实例属性。
(删)同样在运行时删除相关属性
(改)你应该知道是什么意思了。。
(查)不用多说了,就是访问相关属性
#增:
class PeoplePeople:
'定义其属性,"人"的性别'
country = "china" # 类属性
def __init__(self, gender, tall,age):
self.gender = gender
self._tall = tall # 双下下划线私有属性
self.__age = age # 单下下划线私有属性
PeoplePeople.living = "henan" #增加了类名
you = PeoplePeople("男",180,18)
you.name = "liming" #对实例增加属性
print(you.name) #打印新增的属性,打印出来了liming
print(you.living) #打印新增的类属性,打印出来了hena
print(PeoplePeople.living) #同样,打印出来了henan
me = PeoplePeople("女", 170, 17) #新建实例
print(you.living) #打印新增的类属性,打印出来了hena
print(PeoplePeople.living) #同样,打印出来了henan
print(me.name) #发现没有这个属性
输出:
liming
henan
henan
henan
henan
AttributeError: 'PeoplePeople' object has no attribute 'name'
这就是对实例,类进行增,直接 实例名/类名.属性 = 属性值
对实例增加的属性只在当前实例生效,在其他实例中是无法调用的。
增加的类属性就不一样了,哪个实例都可以访问
我们对增还有方法:
PeoplePeople.living = "henan" => setattr(PeoplePeople, "living", "henan")
you.name = "liming" => setattr(you, "name", "liming")
即,setattr(实例名/类名, 属性, 属性值)
#删:
setattr(PeoplePeople, "living", "henan")
you = PeoplePeople("男",180,18)
setattr(you, "name", "liming")
print("开始打印添加后的属性")
print(you.name) #打印新增的实例属性,打印出来了liming
print(you.living) #打印新增的类属性,打印出来了hena
print(PeoplePeople.living) #同样,打印出来了henan
print("删除添加的属性")
del PeoplePeople.living
del you.name
print(you.name)
print(you.living)
print(PeoplePeople.living)
输出:
开始打印添加后的属性
liming
henan
henan
删除添加的属性
AttributeError: 'PeoplePeople' object has no attribute 'name'
AttributeError: 'PeoplePeople' object has no attribute 'living'
AttributeError: 'PeoplePeople' object has no attribute 'living'
del 实例名/类名.属性名
还有别的方法:delattr(实例名/类名, 属性名)
下去自己敲一敲就好了,他两个是等价的
#改:
实例名/类名.属性值 = 新属性
或者
setattr(实例名/类名,要改的属性名,希望的新属性)
更改类名的示例:
setattr(PeoplePeople, "country","USA")
print(PeoplePeople.country)
输出:USA
照着示例,自己练一下呗
#查:
常规的访问就不用说了,讲讲用函数版本的
hasattr(实例名/类名, 属性名) # 返回布尔值,有就True,没有就False
getattr(实例名/类名, 属性名) # 存在就能取到这个值,不存在就报错
自己试一下吧,不会的话看看前面的例子,再不行问问AI?
限制
1.方法的分类:
我们同样可以将方法分为四类:
(1)实例方法:
就是我们最基础的方法,要传入self参数的,对实例进行操作,大家自行即可理解,不再赘述
class PeoplePeople:
def operate_meat(self, meat):
print(f"放入{meat.types}肉")
(2)私有方法:
跟私有属性一模一样,包括命名,保护性,如何访问等,我就直接写例子了,大家根据上文学到的私有属性类比一下吧
class PeoplePeople:
def operate_meat(self, meat):
print(f"放入{meat.types}肉")
def _private1(self):
print("私有方法1")
def __private2(self):
print("私有方法2")
meat = Meat("牛", "方粒状")
you = PeoplePeople()
you.operate_meat(meat)
you._private1()
you.__private2()
输出:
放入牛肉
私有方法1
AttributeError: 'PeoplePeople' object has no attribute '__private2'.
(3)类方法:
就像类属性一样,不同的实例都可以访问,共有的方法
类方法命名有些特殊:使用 @classmethod 装饰器定义,第一个参数是 cls,表示类本身。跟self作用一样
class PeoplePeople:
@classmethod #类方法
def eat(cls):
print("正在吃饭。。。")
def operate_meat(self, meat): #实例方法
print(f"放入{meat.types}肉")
def _private1(self):
print("私有方法1")
def __private2(self):
print("私有方法2")
meat = Meat("牛", "方粒状")
you = PeoplePeople()
me = PeoplePeople()
you.eat()
me.eat()
输出:
正在吃饭。。。
正在吃饭。。。
(4)静态方法:
实例,类不参与的函数
同样,采取装饰器,使用 @staticmethod 装饰器定义,唯一一个没有特殊的参数(self 或 cls)
class PeoplePeople:
@classmethod
def eat(cls):
print("正在吃饭。。。")
@staticmethod #静态方法
def mood():
print("心情很好")
you = PeoplePeople()
me = PeoplePeople()
you.mood()
me.mood()
输出:
心情很好
心情很好
2.对这些方法进行操作:
#查
class PeoplePeople:
@classmethod
def eat(cls):
print("正在吃饭。。。")
@staticmethod
def mood():
print("心情很好")
def operate_meat(self, meat):
print(f"放入{meat.types}肉")
def _private1(self):
print("私有方法1")
def __private2(self):
print("私有方法2")
you = PeoplePeople()
me = PeoplePeople()
print(hasattr(PeoplePeople, "eat"))
print(hasattr(PeoplePeople, "mood"))
print(hasattr(you, "eat"))
print(hasattr(me, "eat"))
print(hasattr(you, "mood"))
print(hasattr(me, "mood"))
print(hasattr(PeoplePeople, "operate_meat"))
print(hasattr(you, "operate_meat"))
print(hasattr(me, "operate_meat"))
#输出全部为True
看看例子,应该就明白了,当然用getattr也可以
#增
给实例增加方法:
实例方法,静态方法,采用实例.方法 = types.MethodType(方法, 实例)
自己可以分析分析为什么输出True和False
import types
#=====================
class PeoplePeople:
@classmethod #类方法
def eat(cls):
print("正在吃饭。。。")
def _private1(self):
print("私有方法1")
def __private2(self):
print("私有方法2")
#=====================
@staticmethod #静态方法
def mood():
print("心情很好")
def operate_meat(self, meat): #实例方法
print(f"放入{meat.types}肉")
you = PeoplePeople()
me = PeoplePeople()
you.mood = types.MethodType(mood, you)
you.operate_meat = types.MethodType(operate_meat, you)
print(hasattr(PeoplePeople, "eat")) #True
print(hasattr(PeoplePeople, "mood")) #False
print(hasattr(you, "eat")) #True
print(hasattr(me, "eat")) #True
print(hasattr(you, "mood")) #True
print(hasattr(me, "mood")) #False
print(hasattr(PeoplePeople, "operate_meat")) #False
print(hasattr(you, "operate_meat")) #True
print(hasattr(me, "operate_meat")) #False
静态方法,类方法,可以采用类名.方法名 = 目标函数
class PeoplePeople:
def operate_meat(self, meat): #实例方法
print(f"放入{meat.types}肉")
def _private1(self):
print("私有方法1")
def __private2(self):
print("私有方法2")
#=====================
@classmethod #类方法
def eat(cls):
print("正在吃饭。。。")
@staticmethod #静态方法
def mood():
print("心情很好")
you = PeoplePeople()
me = PeoplePeople()
PeoplePeople.eat = eat
PeoplePeople.mood = mood
print(hasattr(PeoplePeople, "eat")) #True
print(hasattr(PeoplePeople, "mood")) #True
print(hasattr(you, "eat")) #True
print(hasattr(me, "eat")) #True
print(hasattr(you, "mood")) #True
print(hasattr(me, "mood")) #True
print(hasattr(PeoplePeople, "operate_meat")) #True
print(hasattr(you, "operate_meat")) #True
print(hasattr(me, "operate_meat")) #True
#删
直接del语句删除对应方法
#改
直接用增的操作进行重覆盖即可
1.理解 不同分类的属性方法所对应的作用范围 就好,比如此实例的属性能被彼实例访问吗?
2.尊重私有性,别外部调用