属性: 将一个方法伪装成一个属性 , 在代码的级别上 没有本质的提升 ,但是让其看起来 很合理
伪装 一个属性
class Person:
def _ _init_ _(self,name, weight,hight):
self.name=name
self.weight=weight
self.hight=hight
def bim(self):
return %s的bmi为%s %( self.name, ( self.wejght / ( self.hight**2 ) ) )
p1=Person("哈哈",50,1.63) # 实例化一个对象
p1.bmi ( ) # 这样直接调用类中的方法 可以得到 对象的bmi
但是 这样 得到的bmi 是当成函数方法运算出来的 ,
正常来说 bmi 是一个名词属性 因此 我们可以
通过@property 装饰器将其伪装成一个属性 .
通过@property 装饰器将其伪装成一个属性 :
class Person:
def _ _init_ _(self,name, weight,hight):
self.name=name
self.weight=weight
self.hight=hight
@property # 装饰器 将下列方法伪装成一个对象的属性
def bim(self):
return %s的bmi为%s %( self.name, ( self.wejght / ( self.hight**2 ) ) )
p1=Person("哈哈",50,1.63)
print( p1.bmi ) ====> 得到 结果 # 对象名 . 属性 直接执行
但是若其中有一个年龄的参数 我们应该怎样去修改 其中的参数呢 ? 见下例子
e.g
class Person:
def _ _init_ _(self , name , age ) :
self . name= name
## self. _ _age = age # 年龄 作为 私有成员 保密
self. _ _age = age if type ( age ) is int else print( " 输入格式不对请输入数字 ")
# 这样写 是 用三元 运算法 写的 if 语句
让输入的数字必须是 数字类型的 , 若不是的话 显示不是
@property
def age(self): # 设置一个 伪装 的属性 方法
return self . _ _age 返回 self. _ _age 的值
@age . setter # 添加一个 可以对 属性 进行修改 age 伪装属性和更改的函数和装饰器中的 必须是 相
def age( self , a1 ): 后边的 a1 接收的 是 要 更改的 age 参数 同的才可以
self. _ _age = a1 if type ( a1 ) is int else print( " 输入格式不对请输入数字 ")
# 这样写 是 用三元 运算法 写的 if 语句
让输入的数字必须是 数字类型的 , 若不是的话 显示不是
print ( 666 )
@age.deleter # 删除
def age(self):
del self._ _age # 删除 self .age
p1=Person( "哈哈" , 20 ) # 实例化对象 会自动执行 _ _init_ _传入参数 判断age 然后向下走
p1.age=18 # 这样 是对 属性 进行 修改
当函数 执行到这一步时 会 先 执行 @age . setter
然后将后边的值 传说 给 a1 再向下判断 输入值
print ( p1.age ) === > 18 666 最后结果是修改过的值
del p1.age # 执行 删除 self._ _age 一有这个就会 触发 @age.deleter
print (p1._ _dict_ _) == > { name: 哈哈 }
类方法
: 通过 类名 调用的 类方法 ,
类方法中的第一个参数 是 cls 约定俗成 的
python 自动将 类名 即 类空间 传给 cls
: 通过 对象 调用 类方法
传给 cls 的是 类本身
class A:
def func( self ) :
print( self )
@ classmethod # 类方法
def func1 ( cls ) :
print ( cls )
a1=A()
a1.func() # 相当于 对象名.方法 调用类中的方法 ===> <__main__.A object at 0x00B10F50>
A . func( a1 ) 得到函数内存地址 工作中不常用 得到 内存地址
a1.func1 () # 对象 调用类 中的 类方法 传入的是类本身
相当于 A() . func1 () ===> <class '__main__.A'>
得到的是 一个 类 A 的 类空间
A.func1() # 在有 类方法的 类中
类名 . 类方法() 相当于将类空间传递给了 类方法得第一个参数
因此得到 A的类 类空间 ===> <class '__main__.A'>
类方法的应用场景
1. 类中有些方法 是不需要传入对象的 , 不要对象的一切东西
e.g
class A:
name = " alex "
count=1
def func( self ) :
return A.name + str( A.count+1 )
a=A()
print( a.func() )
class A:
name = "alex"
count =1
@classmethod
def func( cls ):
return cls.name + str(cls.count+1)
a=A()
print(a.func())
2.对类中的静态变量 进行改变时 要用类方法
class A:
age=12
@classmethod
def func( cls ):
cls.age=20
a=A() 实例化一个对象
A.func() 将类空间传给cls 并将其中的 age 赋值为 20
print(A.age)===> 得到结果 20
3.继承中 父类得到子类的空间
在父类中类方法 得到子类的空间 并可以对其进行 任何操作
对子类进行任何操作
e.g
class A:
def func(self):
print(self )
@classmethod
def func1( cls ) :
print(cls)
class B(A):
def f1( self ):
pass
B.func1() ===><class '__main__.B'> 现在b类中找 func1 没有 ,
再到 A类中 找 有 B 类会传给 cls
因为B类名 调用 类方法 因此得到的是 B的类空间
class A:
age=12
@classmethod #类方法
def func( cls ): # 将类空间传给 cls
cls.age=50 # 得到 类空间后 对类空间做改变 将B 中的 age 改为 50
str = "jjj " # 得到 类空间后 对类空间做改变 将B 中的 str 改为 jjj
print( cls.age )
class B(A):
age=22
str="dgg"
B.func() # 通过类名 + 类方法名 得到 类空间
print( B.age ) === > 50
print( B.str ) =====> jjj
普通的方法
class A
age = 12
def func2( self ): #self 子类的对象也能得到子类的内容 但是不能改
print( self )
class B(A) :
age=11
b=B()
print( b.age )
静态方法 : 不需要 对象 ,不需要传参数 直接用的时候 就调用
什么时候用?
1. 如果一个类里边的方法, 既不需要用到 self 中的资源也不需要 用cls中的资源
2. 相当于一个普通函数
3. 但 你由于某种原因 还要把这个方法放在 类中 这个时候 就将 这个方法变为 静态方法
这个某种原因是什么?
1. 完全想用面向对象编程 所有的函数都必须写到类里
2. 某个功能确确实实是这个类方法 , 但是确确实实 没有用到和这个类有关系的资源
优点: 1. 在代码块观赏角度来说 静态方法比较清晰
和普通静态方法相比来说 , 只是一个方法, 若写一堆方法放到一起,太乱不好找
将其放到一个类中, 可以很快找到 然后直接通过类名就可以调用
2. 增加了代码的复用性
class A:
@staticmethod
def func():
print(666)
A.func()===> 666