22.python类的梳理(高阶操作)

今天,我们来把类相关的东西梳理一下。

首先画个思维导图。


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

到这里结束。


希望有志同道合的小伙伴关注我的公众平台,欢迎您的批评指正,共同交流进步。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值