Python类的内置函数

步步为营

这段代码包含的东西比较杂,但是大部分的还是很有用,下面是对这里用到的知识点的总结和提炼,以代码为准绳,步步为营。这段代码主要是在讲两个人去买东西,他们都是类home的实例,只不过一个是家里的男人,一个是家里的女人。他们要各自记住自己买了什么东西,同时作为一个家庭,他们也要知道一共买了多少东西,两个人之间还需要比较一下,提纲挈领的大概就是这么回事。但是中间穿插了很多知识点,在以后的实际开发中可能会用到。

构造函数 _init_

这是我们接触到的第一个Magic Method,有名字可知,其是一个初始化函数,在类实例化的时候首先自动运行的一个函数(严格来说不是第一个)。举个栗子

class One:
  def __init__(self,par=None):
    if par == None:
      print 'No parameter'
    else:
      print 'Follow me:',par
one1=One()
one2=One('Houa!')
##output
#>>>No parameter
#>>>Follow me: Houa!

从输出结果我们看出,在示例化对象一时,自动调用了类里面的__init__函数,由于这里我们没有传入参数,所以直接输出No parameter。需要额外注意的是,在这个__init__函数里,我们使用了默认参数的用法,par=None,这是函数定义时经常使用的,表示我们不传入该参数时,该参数使用的默认值就是定义时所给定的这个None,当然我们也可以None设为我们想设的其他值。我们示例化对象one2时,我们传入了参数,所以自动调用__init__并输出了Parameter is Houa!

全局变量和静态方法
如代码中的第8、9行

total_item=[]
num=0

我们在类的初始化方法(后面介绍)__init__之前定义了两个变量total_item和num分别表示整个家庭所购买的物品和总数,这两个变量在实例化后不同的对象访问都是允许的,且不同的对象内部的这些全局变量都是公共使用的,举个简单的栗子来说

class Two:
  a=0
  def __init__(self):
    Two.a=Two.a+1
    print Two.a
two1=Two()
two2=Two()
Two()
two1.a=0
Two()
##output
#>>>1
#>>>2
#>>>3
#>>>4

切记,在类内部使用这些变量时,要在变量前写上类名,如Two.a,由结果可知,各个对象之间没有什么关联,但是类全局变量a在不同的对象里却是同一个变量,所以才会出现上面的累加效果。但是,我们发现,当我们在类的外部使用像two1.a=0这样的语句来修改这个全局变量时,并没有成功,最有一个Two()输出的4。所以这里我们使用静态方法来实现,但这不是必须的,首先看栗子,我们在上面的类中加入静态方法

class Two:
  a=0
  def __init__(self):
    Two.a=Two.a+1
    print Two.a
  @staticmethod
  def set_a(a):
      Two.a=a
      print Two.a
two1=Two()
Two()
two1.set_a(10)
Two.set_a(100)
print two1.a
##output
#>>>1
#>>>2
#>>>10
#>>>100
#>>>100

静态方法由@staticmethod来修饰,即加在所定义的方法前面,在这里使用静态方法的好处是,我们可以直接使用类名.静态方法的方式来调用,当然对象名.静态方法也能调用,但是对于对象的方法就不能使用类名.方法来调用了。

长度函数 _len_
定义此函数后我们就知道度量长度的内置函数len()作用在这个对象上式什么意思啦,比如在这里我们是想测量此对象买了多少东西,所以,入代码中的37、38行所定义

def __len__(self):
    return len(self.myitem)

那么在后面测试中,直接可以使用print len(man)来打印这个家里的男人买了多少东西,这里输出为2。简单的测试样例如下

class Three:
  def __init__(self, data=[]):
    self.data=data
  def __len__(self):
    print 'you involved __len__'
    return len(self.data)
three=Three([1,2,3])
print len(three)
##output
#>>>you involved __len__
#>>>3
调用属性函数 __getattribute__

这个函数是在类的属性,如变量、函数等等被调用时都会自动运行的一个函数,其中传入的参数为这个属性的名称。此函数是Python新类才引入的,所以在定义类时要继承基类object,这方面知识超出本文范围,请大家自行谷歌

点一下就可以哦。

def __getattribute__(self,attr):
      if attr=='name':
          print '<you have called '+object.__getattribute__(self,attr)+'>'
      return object.__getattribute__(self,attr)

如上代码段,我们简单实现了当类里面的name这个变量被调用时就打印这样一个功能,虽然并没有什么卵用。为了防止循环调用,我们需要使用object._getattribute_(self,attr)这种形式来调用这些变量。

比较函数 _gt__和__eq_
这两个分别是大于和等于的比较,主要是实现当两个对象直接使用大于号>和等于号==进行比较时会产生什么效果,当然还有<,<=,>=,!=这些都可以定义,在这里就省略啦!当定义完成之后我们就可以直接来比较对象了,在上述代码中我们想比较谁买的东西多,所以比较的内容就是个子所买东西的数量,直接引用print man<woman,输出结果则为

>>><you have called may>
>>>you stupid may, you buy the most thing
>>>True

第一行输出是因为我们调用了self.name来打印谁买的多,从而触发了__getattribute__函数而产生的,第二行输出是比较函数内部输出,第三行是打印返回值。

这是属性函数 _setattr_

这个函数在设置类的变量的值是自定调用,比如说实例化对象时,我们要定义self.name=name,这里改变了变量的值,所以就会触发此函数,这个函数有变量名和变量的值两个输入参数。利用这一特性我们可以控制哪些值可以更改那些不可以(其他功能大家自己脑洞开发),具体代码段如下

def __setattr__(self,name,value):
      if name=='ex':
          print 'you don\'t need a ex'
      elif name=='current':
          print 'right, you can set a current value, which is '+value
          self.__dict__[name]=value
      else:
          self.__dict__[name]=value

从这里我们可以看出,当我们要设置ex这个变量是,是不被允许的,直接打印出你不能有ex,当然设置current是被允许的,这就实现了你能有current不能有ex。对于其他不需要考虑的变量,我们直接将其加入类内部的变量字典里,以供使用,具体就是self._dict_[name]=value

对象的字符串表达式 _str_
在没有定义此函数的情况下,当我们打印一个对象时,输出的可能是这个对象的地址,如<main.Three instance at 0x104c622d8>,但是有的时候我们不想要打印这个地址而是其他一些信息,那么我们只要定义这个函数即可。如下代码段

def __str__(self):
    return 'hey, i am '+self.name

那么当你打印女人这个对象时print woman,就会输出hey, i am may,是不是很好玩啊。

迭代器 _iter_

我们知道Python中for循环用的相当多,而这些所要循环的对象都是可迭代的,如for i in range(100)中的range(100)是一个list,是可迭代的,其实这些都是定义了__iter__和next两个函数实现的(前者返回可迭代的对象,后者定义迭代的下一步要干什么)。对于自定义的类,我们也可以使之成为可迭代的,如我们在这里想使得我们的对象man和woman都是可迭代的,即可以直接拿到循环上去用,那么我们可以定义这两个函数。如下我们要实现直接使用对象名来迭代产生对象所购买的物品

def __iter__(self):
      self._index=0
      return self
  def next(self):
      if self._index<len(self.myitem):
          self._index+=1
          return self.myitem[self._index-1]
      else:
          raise StopIteration

其中第二行初始化迭代的位置,next函数告诉我们下一步是返回当前对象的当前_index所对应的物品,当迭代完成就会返回一个迭代到结尾这样一个错误。那么当我们调用如下代码段是就明白为什么有相应的输出了

print 'this class is iterable, the output below is under list(man)'
print list(man)
print 'and iter it again'
print list(man)
##output
#>>>this class is iterable, the output below is under list(man)
#>>>['phone', 'apple']
#>>>and iter it again
#>>>['phone', 'apple']

这了我们直接使用list(man)来产生迭代结果的列表这样一个事实来说明我们的对象可迭代。

总结
我们通过一个两人购物的示例来说明了Python中Magic Method的使用方法,当然这些都是简单粗暴的例子,只能起到说明问题的作用,具体的灵活使用还有待在具体实践中来体现。

注:代码中14~17行无关紧要,感兴趣的可以自己学习学习。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值