前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python学习——数据模型/特殊方法

Python学习——数据模型/特殊方法

作者头像
陆勤_数据人网
发布2020-11-03 14:55:04
4610
发布2020-11-03 14:55:04
举报

数据模型其实是对Python框架的描述,它规范了这门语言自身构架模块的接口,这些模块包括但不限于序列、迭代器、函数、类和上下文管理器。简单来说,数据模型就是Python自身的数据类型,及其包含的特殊方法。这些特殊方法在Java中也被成为‘魔术方法’。

如len(object)调用了__len__特殊方法,list[]调用了__getitem__方法。从根本来说,这些特殊方法能让你的对象实现和支持与迭代、集合、属性访问、运算符、函数和方法、对象创建与销毁、字符串以及管理上下文的语言框架。list[]、+、-、*、/、for i in x这些写法是为了更简介和更具有可读性,实际都是通过特殊方法实现的。

如何调用特殊方法

1.特殊方法的调用是隐式的,通常你的代码无需直接使用特殊方法。除非有大量的元编程存在,直接调用特殊方法的频率应该远远低于你去实现它们的次数。唯一的例外可能是__init__方法,你的代码里可能经常会用到它,目的是在你的子类的__init__方法中调用超类的构造器。

2.通过内置的函数(例如len、iter、str等)来使用特殊方法是最好的选择。这些内置函数不仅会调用特殊方法,通常还提供额外的好处,而且对于内置的类来说,它们的速度更快。

3.不要自己想当然地随意添加特殊方法,比如_foo_之类的,因为虽然现在这个名字没有被python内部使用,以后就不一定了。

部分示例

__len__

代码语言:javascript
复制
class Test:
    def __len__(self): #重写__len__方法
        return 1

if __name__=="__main__":
   t = Test()
   print(len(t)) #输出为1

__getitem__

代码语言:javascript
复制
import collections


Card = collections.namedtuple('Card',['rank','suit'])


class FrenchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        self._cards = [Card(rank,suit) for rank in self.ranks
                       for suit in self.suits]

    def __getitem__(self, item):
        return self._cards[item]

if __name__=="__main__":
    deck = FrenchDeck()
    print(deck[0]) #使用deck[0]时会调用__getitem__方法,解释器会将0传递给__getitem__(self, item)中的item参数
    print(deck[1:4]) #使用切片操作时也会调用__getitem__方法,解释器会传递slice(1, 4, None)item参数

__repr__、__str__、__abs__、__add__、__mul__、__bool__

代码语言:javascript
复制
from math import hypot

class Vector:
    def __init__(self,x=0,y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return "Vector(%r,%r)" % (self.x,self.y)

    def __str__(self):  # 如果类中同时有__str__和__repr__,则调用print是会先使用__str__
        return "Vector(%r,%r)" % (self.x,self.y)

    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)

    def __abs__(self):  # abs本来是绝对值,在二维向量中指模
        return hypot(self.x, self.y) #返回三角形的斜边

    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)

    def __bool__(self):
        return bool(abs(self))

if __name__ == "__main__":
    v = Vector(3,4)
    print(v)    #返回Vector(3,4)
    if v:
        print(abs(v)) #返回5.0
    v2 = Vector(1,2)
    print(v * 3)    #返回Vector(9,12)
    print(v + v2)   #返回Vector(4,6)

__repr__和__str__的区别在于,后者是在str()函数中被使用,或是在用print打印函数打印一个对象的时候才被调用。如果你只想实现这两个特殊方法中的一个,__repr__是更好的选择,因为如果一个对象没有__str__函数,而python又需要调用它的时候,解释器会用__repr__作为代替。 因此在使用print()函数时,解释器会按照__str__,__repr__的顺序寻找。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据科学与人工智能 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如何调用特殊方法
  • 部分示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档