静态方法
什么是特性property:
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
圆的周长和面积:
import math
class Circle:
def __init__(self,radius): #圆的半径radius
self.radius=radius
@property
def area(self):
return math.pi * self.radius**2 #计算面积
@property
def perimeter(self):
return 2*math.pi*self.radius #计算周长
c=Circle(10)
print(c.radius)
print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
print(c.perimeter) #同上
'''
输出结果:
314.1592653589793
62.83185307179586
'''
注意:此时的特性area和perimeter不能被赋值
c.area=3 #为特性area赋值
'''
抛出异常:
AttributeError: can't set attribute
'''
为什么要用property
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
除此之外,看下:
ps:面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开
python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现
class Foo:
def __init__(self,val):
self.__NAME=val #将所有的数据属性都隐藏起来
@property
def name(self):
return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)
@name.setter #可以对property的属性方法设置,首先进行了检验,保证了设置的值为int类型
def name(self,value):
if not isinstance(value,str): #在设定值之前进行类型检查
raise TypeError('%s must be str' %value)
self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME
@name.deleter # 定义不能删除静态属性,抛出异常
def name(self):
raise TypeError('Can not delete')
f=Foo('egon')
print(f.name)
# f.name=10 #抛出异常'TypeError: 10 must be str'
del f.name #抛出异常'TypeError: Can not delete'
一 类中定义的方法分为两类:
绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入)
1.绑定到类的方法:用classmethod装饰器装饰的方法。为类量身定制.
类.boud_method(),自动将类当作第一个参数传入,(其实对象也可调用,但仍将类当作第一个参数传入)。
2. 绑定到对象的方法:没有被任何装饰器装饰的方法:
为对象量身定制
对象.boud_method(),自动将对象当作第一个参数传入(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)
二:非绑定方法:用staticmethod装饰器装饰的方法:
1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说,就是一个普通工具而已.
注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说
绑定给类的方法(classmethod)
classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数(即便是对象来调用也会将类当作第一个参数传入),python为我们内置了函数classmethod来把类中的函数定义成类方法.
class Room():
name = "房子"
def __init__(self, name, type, width, lenth, hight):
self.name = name
self.type = type
self.width = width
self.lenth = lenth
self.hight = hight
@property #静态方法
def cal_area(self):
return self.width * self.lenth
def cal_volume(self):
return self.width * self.hight * self.lenth
@classmethod #类方法
def tell_info(cls):
print("类得属性", cls.name, )
print(cls)# cls.hight 这个是实例的数据属性 类方法调用不到
r1 = Room("alex", "厕所", 100, 100, 1000)
# print(r1.cal_area)
print(r1.tell_info()) # 实例 方法也可以调用类方法 毕竟实例本身没有方法
# print(Room.tell_info()) # 类调用方法,并且把类本身的数据属性传递给类方法
三 非绑定方法
在类内部用staticmethod装饰的函数即非绑定方法(类的工具包),就是普通函数,statimethod不与类或对象绑定,谁都可以调用,没有自动传值效果。
class Room():
def __init__(self, name, type, width, lenth, hight):
self.name = name
self.type = type
self.width = width
self.lenth = lenth
self.hight = hight
@property
def cal_area(self):
return self.width * self.lenth
def cal_volume(self):
return self.width * self.hight * self.lenth
@staticmethod
def test():
print("我是静态方法,是类得工具包") #不能访问类得属性与实例属性
def NOT_test():
print("我不是静态方法,如果实例调用我 类会自动给实例传递一个参数")
r1 = Room("alex", "厕所", 100, 100, 1000)
print(r1.cal_area)
r1.test()
print(r1.test) # <function Room.test at 0x00000000011A7840> 普通函数
# r1.NOT_test() #会报错因为这个实例的类直接把自己自动传给了这个Ttest方法,导致传递多了参数
Room.NOT_test() # 这个不会报错因为累调用自己的方法 不会把自己传进去
四 classmethod与staticmethod的对比 :
import settings
class MySQL:
def __init__(self,host,port):
self.host=host
self.port=port
@staticmethod
def from_conf():
return MySQL(settings.HOST,settings.PORT)
# @classmethod #哪个类来调用,就将哪个类当做第一个参数传入
# def from_conf(cls):
# return cls(settings.HOST,settings.PORT)
def __str__(self):
return '就不告诉你'
class Mariadb(MySQL):
def __str__(self):
return '<%s:%s>' %(self.host,self.port)
m=Mariadb.from_conf()
print(m) #我们的意图是想触发Mariadb.__str__,但是结果触发了MySQL.__str__的执行,打印就不告诉你: