Ⅰ、类属性、类方法(类和实例都能调用类属性和类方法)
类是一个特殊的对象,Python 中 一切皆对象:
class AAA: #定义的类属于 类对象
obj1 = AAA() #属于 实例对象
除了封装 实例 的 属性 和 方法外,类对象 还可以拥有自己的 属性 和 方法:
·类属性
·类方法(方法前面要加上@classmethod装饰器。不用实例化就可以执行类的方法)
通过 类名. 的方式可以 访问类的属性 或者 调用类的方法(方法的参数中要用cls参数且放到最前)
class A:
a=1
@classmethod
def aa(cls):
print("这是类方法")
s=A()
print(A.a)#调用属性
1
A.aa() #调用方法
这是类方法
print(s.a)
1
s.aa()
这是类方法
class B:
def __init__(self):
self.a=1
def aa(self):
print("这是实例方法")
m=B()
>>>print(B.a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'B' has no attribute 'a'
>>>B.aa()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: aa() missing 1 required positional argument: 'self'
>>>B.aa(m)#具体原因可以参考之前self的文章,请点入口1
这是实例方法
>>>print(m.a)
1
>>>m.aa()
这是实例方法
Ⅱ、私有属性与公有属性
在定义类的属性时,如果属性名以两个下划线“__”开头则表示是《私有属性》,否则是《公有属性》。
①私有属性在类的外部不能直接访问,需要调用对象的“公有成员方法”来访问,
或者
②通过python支持的特殊方式来访问。
Python提供了访问私有属性的特殊方式,可用于程序的测试和调试,对于成员方法也有同样性质。方法如下:
对象名._类名+私有成员
例如:访问Car类私有成员__weight
car1._Car__weight
注意:私有属性是为了数据封装和保密而设的属性,一般只能在类的成员方法(类的内部)中使用访问,虽然Python支持一种特殊的方式来从外部直接访问类的私有成员,但是并不推荐这种做法。
#在类的成员方法(类的内部)中使用访问
class Car:
price =1000 #定义类属性,类和对象访问
def __init__(self,c,w):
self.color=c #定义共有属性color,对象访问
self.__weight=w #定义私有属性__weight,类和对象都不能访问
def siyou(self):
return self.__weight
car1 = Car("red",10.5)
>>>print(Car.price)
1000
>>>print(Car.color)
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: type object 'Car' has no attribute 'color'
>>>print(car1.price)
1000
>>>print(car1.color)
red
>>>print(car1.__weight)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Car' object has no attribute '__weight'
>>>print(car1.siyou())
10.5
Ⅲ、私有方法、公有方法
私有方法、公有方法都属于对象,私有方法的名字以两个下划线“__”开始,每个对象都有自己的公有方法和私有方法,在这两类方法中可以访问属于类和对象的成员;
①公有方法通过对象名直接调用,
②私有方法不能通过对象名直接调用,只能在属于对象的方法中通过“self”调用,或者外部通过Python支持的特殊方式来调用
class Test:
def __test2(self):
print("这是私有方法")
def test(self):
print("这是公有方法1")
def _test(self):
print("这是公有方法2")
self.__test2()
t=Test()
>>>t.test()
这是公有方法1
>>>Test.test()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: test() missing 1 required positional argument: 'self'
>>>t._test()
这是公有方法2
这是私有方法
>>>t.__test
'Test' object has no attribute '__test'
Ⅳ、静态属性、类方法(上面提到过)、静态方法
一、静态属性
静态属性说的就是数据属性,把方法变成像属性一样调用
1、定义一个房间的类,求下这个房间的面积
class Room:
def __init__(self,name,ower,width,length,heigh):
self.Name=name
self.Ower=ower
self.Width=width
self.Length=length
self.Heigh=heigh
def cal_area(self):
print("%s 住的%s 总面积是%s平米的地下室" %(self.Ower, self.Name, self.Width * self.Length))
r1=Room("厕所","北爷",2,2,20000)#实例化出来一个实例r1,实例化的过程就是执行__init__
r2=Room("北京","喵爷",20,60,20000)#实例化第二个实例
r1.cal_area()#实例调用类的函数属性会自动传实例本身作为参数
r2.cal_area()#实例调用类的函数属性会自动传实例本身作为参数
输出结果:
北爷 住的厕所 总面积是4平米的地下室
喵爷 住的北京 总面积是1200平米的地下室
1、1 property装饰器
class Room:
def __init__(self,name,ower,width,length,heigh):
self.Name=name
self.Ower=ower
self.Width=width
self.Length=length
self.Heigh=heigh
@property #把一个方法变成一个数据属性
def cal_area(self):
print("%s 住的%s 总面积是%s平米的地下室" %(self.Ower, self.Name, self.Width * self.Length))
r1=Room("厕所","北爷",2,2,20000)#实例化出来一个实例r1,实例化的过程就是执行__init__
r2=Room("北京","喵爷",20,60,20000)
r1.cal_area#用了property这个装饰器之后,实例在调用函数属性就等于调用数据属性,不用加()就可以调用
r2.cal_area
输出结果:
北爷 住的厕所 总面积是4平米的地下室
喵爷 住的北京 总面积是1200平米的地下室
1.2 这样还不行。因为正常的数据属性直接运行是没有返回值的
现在改为了直接return一个返回值,现在用起来的效果就是跟调用数据属性是一模一样的了,property这个装饰器就是把类的函数属性变为数据属性,也就是封装成了数据属性
class Room:
def __init__(self,name,ower,width,length,heigh):
self.Name=name
self.Ower=ower
self.Width=width
self.Length=length
self.Heigh=heigh
@property #把一个方法变成一个数据属性
def cal_area(self):
# print("%s 住的%s 总面积是%s平米的地下室" %(self.Ower, self.Name, self.Width * self.Length))
# return (self.Width * self.Length)
return "%s 住的%s 总面积是%s平米的地下室" % (self.Ower, self.Name, self.Width * self.Length)
r1=Room("厕所","北爷",2,2,20000)#实例化出来一个实例r1,实例化的过程就是执行__init__
r2=Room("北京","喵爷",20,60,20000)
print(r1.cal_area)#用了property这个装饰器之后,实例在调用函数属性就等于调用数据属性,不用加()就可以调用
print(r2.cal_area)
print(r1.Name)#调用r1这个实例的数据属性
print(r2.Name)#调用r2这个实例的数据属性
#输出结果:
北爷 住的厕所 总面积是4平米的地下室
喵爷 住的北京 总面积是1200平米的地下室
厕所
北京
二、python给我们提供了classmethod这个装饰器,只要用了这个方法, 就表示这个装饰器下面的方法是专门给类用的
这个方法就是只是类在调用类的方法,跟实例没关系,只要加了classmethod就只能供类调用
class Room:
tag=1#定义一个类的数据属性
def __init__(self,name,ower,width,length,heigh):
self.Name=name
self.Ower=ower
self.Width=width
self.Length=length
self.Heigh=heigh
@classmethod#这个装饰器是专门供类使用的方法
def tell_info(cls):#cls代表类本身
print(cls)
print("---",cls.tag)#等价于Room.tag
Room.tell_info()#会自动把类本身传给cls
#输出结果
<class '__main__.Room'>
--- 1
三、静态方法 叫类的工具包,不跟类绑定也不跟实例绑定。也就是说都能用
class Room:
tag=1#定义一个类的数据属性
def __init__(self,name,ower,width,length,heigh):
self.Name=name
self.Ower=ower
self.Width=width
self.Length=length
self.Heigh=heigh
@classmethod#这个装饰器是专门供类使用的方法
def tell_info(cls):#cls代表类本身
print(cls)
print("---",cls.tag)
@staticmethod#静态方法 叫类的工具包,不跟类绑定也不跟实例绑定
def wash_body(a,b,c):
print("%s %s %s 正在洗澡" %(a,b,c))
Room.wash_body("北爷","喵爷","修电脑")#用类调用washbody这个方法
r1=Room("厕所","北爷",2,2,20000)#实例化一个实例r1
r1.wash_body("北爷","喵爷","修电脑")#用实例调用washbody这个方法
#输出结果:
北爷 喵爷 修电脑 正在洗澡
北爷 喵爷 修电脑 正在洗澡
总结:
静态属性:property类和实例都可以访问静态属性(把函数封装成一个数据属性,让外面的人感受不 到是调用的函数属性)
类方法: classmethod类访问类方法,实例也能访问类方法
静态方法:staticmethod 用类可以调用静态方法,实例也可以调用静态方法不跟类和实例绑定,只叫类的工具包
Ⅴ、python的命名规范
python中有几种比较有意思的命名的方式,__xxx__
、__name
、_name
、,下面分别说它们的用处。
【__xxx__】
在Python中,所有以“__”双下划线包起来的方法,都统称为“Magic Method”(魔术方法),是可以直接访问的。例如类的初始化方法 __init__
,Python中所有的魔术方法均在官方文档中有相应描述
def __init__(self, name)
【__name】
双下划线开头,表示的是私有变量,为了让内部属性不被外部访问。
【_name】
_xxx被看作是“私有的”,在模块外不可以使用,在类外可以用。当变量是私有的时候,用_xxx 来表示变量是很好的习惯。单下划线 开始的成员变量叫做保护变量,意思是只有本模块、类、对象和子类对象自己能访问到这些变量,被导入时,该变量不能引用;