详讲类中的属性和方法

详讲类中的属性和方法

引言

上篇文章,我们对类,实例,属性,方法有了一个初步的了解。会书写创建,访问相关的属性方法,也深入理解了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.尊重私有性,别外部调用

你可能感兴趣的:(python,python,开发语言)