类空间中有:
-
静态属性: 所有对象动统一拥有的属性
-
方法
-
类方法 :不使用类中的命名空间也不使用对象的命名空间:一个普通函数,没有默认参数 ,cls 表示类 self 表示对象,自动传值为类名,类可以调用自己类中的方法。
-
静态方法 不论传不传值,都可以用,该类或对象已经和该方法没有关系了
-
property方法
-
property方法
property 装饰器 保护一个变量,在修改的时候能够添加一些保护条件, 相对于C++来说,C++每个变量都会设置输入的类型和改动时的类型。而python只是在加了property装饰器的时候限制了类型。
setter 装饰器 1,被property装饰的方法, 2 实现了一个同名方法 3 被setter装饰器装饰了 4 该方法名放setter前。 4个条件才能用setter装饰器
例1:
class Student:
def __init__(self, name):
self.__name = name # 把name设置为私有属性,为了不让不让看和改动
@property # 把name这个方法伪装成了属性,property是属性的意思,这样也可以用通常的方法看到name这个属性一样,只是不可以改
def name(self): # 装饰器一定要紧挨着此方法,中间不能有换行
return self.__name
@name.setter # 改name的操作在这一步,限制了条件,这样就不可以随便更改此私有属性。
def name(self, new):
if type(new) is str:
self.__name = new
linda = Student('linda')
print(linda.name) # linda # 直接打印了name方法返回的值
linda.name = 'laura' # 修改name的值,实际是执行了被setter装饰的方法,因为被装饰器property装饰了,所以修改的时候,用通常
修改属性的方法就可以,因为要规范代码的格式,如果要删除私有属性,总不能还价格类名在加个双下划线把,python的语法就是优美,简洁。
print(linda.name) # laura
例2;
class A:
def __init__(self, name):
self.name = name
@property
def func(self):
return self.name
@func.setter
def func(self, new): # 修改
self.name = new
@func.deleter
def func(self):
del self.name
a = A('laura')
print(a.func) # laura # 执行被property伪装的方法
print(a.__dict__) # {'name': 'laura'}
a.func = 123 # 修改name
print(a.func) # 123
print(a.__dict__) # {'name': 123}
del a.func # 删除一个property属性的时候会执行deleter装饰的方法
print(a.__dict__)
例3
class Goods:
__discount = 0.8 # 私有变量,折扣不想让顾客看到
def __init__(self, price):
self.__price = price # 价格也不想让顾客看见
self.name = 'apple'
@property # 将price这个伪装成属性, 因为想让顾客看到我设置的价格
def price(self):
return self.__price * Goods.__discount
@price.setter
def price(self, new):
if new is int: # 如果改动后的价格是整数
self.__price = new # 就可以更改,否则price还是原来的不变
print(self.__price) # 打印改动后的价格
@price.deleter # 如果想删除该变量,通常格式是在类外面是删除不了的,所以设置了一个方法,用来删除变量。
def price(self):
self.__price = 50
del self.__price
apple = Goods(10)
print(apple.price) # 8.0
print(apple.__dict__) # {'_Goods__price': 10, 'name': 'apple'}
del apple.price # 删除price这个对象的私有属性,实际是执行了被deleter装的方法,由于被装饰成了属性,所以删除的格式也像删除属性的方法,
print(apple.__dict__) # {'name': 'apple'}
del apple.name # 此代码就是正常的删除对象空间的普通的属性。
print(apple.__dict__) # {}
'''
综上所述,一个方法被伪装成属性之后,应该可以执行一个属性的增删改查的操作,
增加和修改,对应setter装饰的方法,这个方法有一个必传的参数,表示赋值的时候等号后面的值
删除一个属性,对应着被deletter装饰的方法,这个方法并不能在执行的时候真的删除这个属性。
而是在代码中执行了什么就有什么效果,就是说实际上本质还是一个函数,函数本身是不能增删改查,而是
函数代码块有什么,函数就执行什么。
'''
- @classmethod 类方法 只使用类中的资源,且这个资源可以直接用类名引用和使用,那这个方法应该被该为类方法
class Goods:
pass
__discount = 0.8
def __init__(self, price):
self.__price = price
self.name = 'apple'
@classmethod # 类方法 如果类中的私有属性,如折扣,不想让别人看到,或改动的时候不想通过类名直接改,而是要加一些限制条件,那可以定义一个函数去改,而如果定义一个函数,那必然要传一个对象的self参数,这是python底部已经设置好的,那我不想传对象这个参数,直接传我要改动的新值就好了,类方法可以解决这件事情,默认传了的参数是类名
def change_discount(cls, new):
cls.__discount = new
Goods.change_discount(0.7)
print(Goods.__dict__)
apple = Goods(10)
banana = Goods(20)
apple.change_discount(0.7)
print(apple.price)
- @staticmethod 静态方法
class Student:
@staticmethod # 静态方法 static 静止的 被staticmethod装饰过的方法可以不用传值,直接被类名和对象调用
def login():
print('IN LOGIN')
a = Student()
a.login() # IN LOGIN # 可以被对象调用
Student.login() # IN LOGIN # 可以被类名调用
- 判断是否是类中的方法还是普通函数
class Foo():
@classmethod
def class_method(cls):
pass
@staticmethod
def static_method(): pass
from types import MethodType, FunctionType
obj = Foo()
print(isinstance(Foo.class_method, MethodType)) # True 判断class_method 是不是方法类型
print(isinstance(Foo.static_method, FunctionType)) # True 判断static_method 是不是函数类型
print(obj.static_method) # <function Foo.static_method at 0x000002244107ABF8> 返回的是函数类型的地址
类方法,普通方法,静态方法的区别
# 类方法,静态方法,普通方法的区别
class A():
@classmethod
def clas(cls): # 定义一个类方法
print('clas')
def common(self): # 普通方法
print('common')
@staticmethod
def sta(): # 静态方法
print('sta')
A.clas() # clas 类名直接调用类方法,不用传参,默认参数是类名
A().clas() # clas 类的实例化对象也可以调用类方法
A.common('aa') # common 类名直接调用普通方法,必须传参,self
A().common() # common 当对象调用普瑞方法时,不用传参。因为self就是实例化对象,默认吧自己穿给了self。
A.sta() # sta 类名调用静态方法
A().sta() # sta 对象调用静态方法,都不用传参
类中定义的函数什么情况下是方法method,什么情况下是函数function
class Foo:
School = 'xihu'
Country = 'China'
language = 'Chiness'
@classmethod
def class_method(cls):
print(cls.School)
@staticmethod
def static_method():
print('in staticmethod')
def common(self):
print('in common')
f = Foo()
print(Foo) # <class '__main__.Foo'> 类Foo的再内存上的地址
print(f.common) # <bound method Foo.common of <__main__.Foo object at 0x000002CC931ABA20>> 对象调用普通方法 : method
print(Foo.common) # <function Foo.common at 0x000001A4DD69CC80> 类名调用普通方法 : function
print(Foo.static_method) # <function Foo.static_method at 0x000002A774F7CD08> 类名调用静态方法: function
print(f.static_method) # <function Foo.static_method at 0x000002482175CD08> 对象调用静态方法:function
print(f.class_method) # <bound method Foo.class_method of <class '__main__.Foo'>> 对象调用类方法 method
print(Foo.class_method) # <bound method Foo.class_method of <class '__main__.Foo'>> 类调用类方法 method