今天,我们来把类相关的东西梳理一下。
首先画个思维导图。
1)字段
我们首先要明白,我们之前讲的大部分情况是对对象或者说是实例进行操作的。但是,事实上类也是有各种操作的。我们之前一直所说的”属性“其实是字段。你可能要骂我了,你之前不是说是属性吗?这个是字段,那后面的是什么??各位看官先把刀放下,等我给您细细道来。
字段分为两种,一种是普通字段,一种是静态字段。他们两个之间的区别是:前者是针对对象而言的,存放在内存的对象区域,有一个对象,存一个字段。后者是针对类而言的,有一个类,放一个字段。
示例代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class MyClass(object):
class_attr='quinn lee'#静态字段
def __init__(self,heigh):#普通字段
self.heigh=heigh
object=MyClass(180)
print(object.heigh) #直接访问普通字段。
print(MyClass.class_attr)#直接访问静态字段
由代码可看出,访问普通字段需要对象。访问静态字段,需要类。
接下来是方法。
2)方法
方法有三种,普通方法,类方法,静态方法。这三种方法都是存放于内存的类空间中,区别只是调用方式不同。
- 普通方法:之前所介绍的方法就是普通方法,至少有一个参数(self)。是针对对象而言的。
- 类方法:类方法是针对类的方法,至少有一个参数(cls)。定义前需要申明一个装饰器@classmethod。
- 静态方法:也是针对类的方法,没有参数。定义前需要申明装饰器@staticmethod
接下来是示例代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class MyClass(object):
class_attr='quinn lee'
def __init__(self,heigh):
self.heigh=heigh
def normal_method(self):
print('normal')
@classmethod
def cls_method(cls):
print('class')
@staticmethod
def sta_method():
print('static')
object=MyClass(180)
print(object.normal_method())
print(object.sta_method())
print(object.cls_method())
输出结果:
normal
None
static
None
class
None
这里有个问题,为什么后面跟一个None??因为不用print
3)属性
你可能看到导图中的箭头了。没错,属性就是方法(普通方法)的变种。我们首先看变种的基本使用:
(1)基本使用
示例代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class MyClass(object):
class_attr='quinn lee'
def __init__(self,heigh):
self.heigh=heigh
@property
def attr(self):
return "quinn lee"
obj=MyClass(180)
print(obj.attr)
我们可以从代码中知道,需要提前定义装饰器@property。然后定义一个参数(有且仅有一个),且调用时无需括号。是对一个对象,对象,对象调用。
这里你可能迷糊了,这有什么意义呢?这种定义属性的方式可以制造出和访问字段完全相同的假象!!!这就是之前为什么也把字段叫做属性的原因,这是一个方法对应一个值,那个是一个字段,对应一个值。
(2)属性定义的方式
有两种,一种就是上面讲的用装饰器,但是类中有经典类和新式类,上面的是经典类,也就不多说了。这里就介绍新式类。新式类具有三种装饰器,首先得申明主装饰器@property然后剩下两个装饰器同属性(方式)名有关。示例代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class MyClass(object):
class_attr='quinn lee'
def __init__(self,heigh):
self.heigh=heigh
@property
def att(self):
print ('@property')
@att.setter
def att(self,value):
print ('@attr.setter')
@att.deleter
def att(self):
print ('@attr.deleter')
obj=MyClass(180)
obj.att=13
del obj.att
输出结果:
@attr.setter
@attr.deleter
记着:你要操作的目标是属性(伪字段),也就是只关注你定义的属性,调用的是属性,不要在乎其他的形参。
下面举个例子:
# -*- coding: utf-8 -*-
#!/usr/bin/env python3
class Good(object):
def __init__(self,orig_price,discount):
self.orig_pri=orig_price
self.discount=discount
@property
def price(self):
self.real_price=self.discount*self.orig_pri
return self.real_price
@price.setter
def price(self,value):
self.orig_pri=value
return self.orig_pri #此句并未起作用,这些都是为price主属性服务的,只能修改主属性中的orig_price值。
@price.deleter
def price(self):
del self.orig_pri
obj=Good(100,0.8)
print(obj.orig_pri)#对字段操作
print(obj.price) #得到属性
obj.price=90 #更改属性
print(obj.price) #得到属性
del obj.price #删除属性
输出结果如下:
100
80.0
72.0
这里我们定义了一个商品类,首先定义了两个普通字段,orig_price,discout。接下来,我们将这两个字段绑定到对象(实例)上。接下来,我们定义了一个价格属性,然后设置两个附属性。
我们如果将price.setter属性改成下面的结果:
@price.setter
def price(self,value):
self.real_price=value
return self.real_price #并未修改属性成功,验证上面,只能修改orig,discount
输出结果:
100
80.0
80.0
这里,我们希望将real_price修改为90且直接返回。很明显,我们修改失败了。这是什么呢?
分析:
这里的设置的三个属性看起来都是平等的,但事实上主属性,也就是property属性地位最高。附属性都是围绕这个主属性来操作的。当修改price属性之后,先与主属性的值做比较,如果不一致的话,以主属性为准。所以我们这里只能对普通字段(orig_price和discount)进行操作,然后再返回到主属性中操作,通过改变他们的值来修改。
接下来,就是静态字段方式。
静态字段方式
当用静态字段方式的时候,经典类和静态类无区别。
示例代码如下:
# -*- coding: utf-8 -*-
#!/usr/bin/env python3
class MyClass(object):
def __init__(self):
pass
def attr(self):
return 'quinn lee'
att=property(attr)#这里我们静态字段property将方法类型转化成了属性。
obj=MyClass()
print(obj.att)
输出结果:
quinn lee
分析:
这里我们当作,用静态字段将attr方法强制转化成了属性,然后赋给属性名。其实我们通过静态字段和普通字段就已经知道,普通字段是针对对象,在对象内存当中。静态字段是针对类而言,保存在类内存当中。这里就不难理解了。
有一点注意的地方是,这种方式有四个参数,比上种方式多一个字符串参数,用于描述该属性。其各个属性调用方式是完全一样的。
示例代码如下:
# -*- coding: utf-8 -*-
#!/usr/bin/env python3
class Good(object):
def __init__(self,orig_price,discount):
self.orig_pri=orig_price
self.discount=discount
def get_price(self):
self.real_price=self.discount*self.orig_pri
return self.real_price
def set_price(self,value):
self.orig_pri=value
def del_price(self):
del self.orig_pri
price=property(get_price,set_price,del_price,'我是一个字符串!')
obj=Good(100,0.8)
print(obj.orig_pri) #得到属性
print(obj.price) #得到属性
obj.price=90 #更改属性
print(obj.price) #得到属性
del obj.price #删除属性
输出结果:
100
80.0
72.0
到这里结束。
希望有志同道合的小伙伴关注我的公众平台,欢迎您的批评指正,共同交流进步。