用Python数据模型编写Pythonic代码

特殊方法

>这种明显的奇怪性是冰山一角,当正确理解时,它是我们所谓的pythonic的关键。冰山被称为python数据模型,它描述了您可以用来使自己的对象与最惯用的语言功能效果很好的api。

>关于python数据模型的特别之处。我们没有给出个人答案,而是为什么不深入研究,并通过了解数据模型来了解我们可以完成的工作。数据模型只是谈论如何表示数据。在python中,数据由对象表示或听起来有些技术,对象是python的数据抽象。数据模型为我们提供了一个api,该api允许我们的对象在python编程的“引擎盖下”效果很好。

>在我们深入研究python数据模型中,我们将专门关注特殊方法。特殊方法是具有特殊名称的类功能,这些函数由特殊语法调用。在我们的班级定义中定义这些特殊方法可以为我们的课堂实例提供一些非常酷的python权力,例如迭代,操作员超载,与上下文管理者(’with with with with关键字),正确的字符串表示和格式化等良好合作。为了向您展示如何在课堂中实现这些特殊功能,我们将考虑两个情况的示例,其中使用这些特殊功能会使我们的代码更清晰,更重要。

>

第一个示例是我想到的一些外部解决方案,因为在python中创建了一个简单的岩纸剪辑游戏,第二个本质上将有点数学上有点数学’m将带您浏览每行代码

一个简单的岩石剪刀游戏

>以防万一您不熟悉岩纸剪辑游戏,它最初是在两个人中玩的手游戏,其中涉及摇滚,纸或剪刀的迹象。了解游戏的整个历史并不重要,重要的是知道如何确定获胜者。在传统的环境中,岩石的手势总是会击败剪刀,但会输掉纸,剪刀的手势会击败纸,输给岩石,显然,纸会输给剪刀并击败摇滚。我们可以总结这一点,如下所示

>

image of rock, paper, scissors game对于我们对此游戏的python仿真,我们将仅将玩家数量限制在两个,一个玩家将是计算机,另一个玩家将是用户。另外,这不是机器学习文章或有关计算机视觉的文章,我们的用户仍然必须在终端上的岩石,纸张和剪刀之间输入选项才能工作。在进行实际编码之前,我们可以退后一步并考虑希望我们的python脚本成为现实是很好的。为了解决这一挑战,我将使用随机模块启用计算机选择岩石,纸或剪刀的随机选项。为了实现我们的代码如何评估获胜者,我将做出以下假设:>

>我也要采取oop方法;我们的岩石,纸和剪刀将被视为对象而不是弦变量。与其为每个类别创建三个单独的类,不如创建一个可以代表其中任何一个的类。这种方法还可以让我向您展示特殊方法如何使生活更轻松。现在到一个有趣的方面!

类定义

>命名我们的rps听起来可能有些奇怪,但是我发现“ rps”这个名字是一个很好的合适,因为每个字母都来自缩写,r for rock,p for paper for paper,s for scissors。这里要注意的是,创建我们的班级实例需要两个参数:选择和名称。我们已经说过,脚本的用户必须在终端上输入其选定选项,而不是让我们的用户输入“纸张”(对他们来说可能是如此压力)输入“ p”(或“ p”)以选择“纸”,这就是选择的目的。名称属性是实际名称,例如“纸”。因此,现在我们知道了每个参数的目的,我们现在可以通过创建一个实例

来检查我们的类

>>> p = rps('p', 'paper') # create an instance>>> p.name# return : paper>>> p.pick# return : p>>> print(p)# return : 

>创建了类实例并具有正确的属性,但请注意,当我们尝试打印持有类实例的变量内容时,我们得到了什么。在了解我们的类实例如何返回奇数字符串的技术细节之前,让我们通过添加单个特殊功能并查看差异来更新我们的类定义。

现在,让我们创建一个实例,然后尝试再次打印我们的类实例

>>> p = rps('p', 'paper')>>> print(p)# return : rps(p, paper)

正如我们所看到的,通过定义’

repen>’的方法,我们可以取得更好的结果。让我们对我们的班级定义进行一次更改。

现在,让我们创建一个实例并重新测试。

>>> p = rps('p', 'paper')>>> p# return : rps(p, paper)>>> print(p)# return : paper>>> str(p)# return : 'paper'>>> repr(p)# return : 'rps(p, paper)'
要知道这里发生了什么,我们需要了解打印功能。打印功能将所有非关键字参数(如我们的p变量)转换为使用内置python类str的字符串。如果在我们的变量上调用str()失败,则python会落在内置的reper函数上。当我们的对象上调用str时,它会寻找__str__方法,如果没有发现,则会失败,然后搜索__repr__方法。 __str__和__repr__方法都是用于字符串表示我们对象的特殊方法。 __repr__方法给出了我们对象的官方字符串表示,而__str__方法给出了我们对象的友好字符串表示。我通常会说__repr__方法就像与另一个开发人员交谈,通常显示如何打电话给我们的班级,而__str__就像与我们程序的用户交谈(如在这种情况下的播放器),您通常只想返回一个简单的字符串,例如“纸”,以向用户展示他选择的内容。>

>尽管我将__repr__和__st__表示为我们类定义中的两个特殊功能,但实际上有第三种特殊方法,是的,它是最常见的方法,即__init__函数。它用于初始化我们的课程,并在返回我们的类实例之前通过__new__ __ ________________。我是否只是提到了我们尚未定义的另一种特殊方法?是的,我做到了。您可能会感兴趣的是,python会自动为我们的班级添加其他一些特殊方法。您可以通过在我们的类实例上调用内置功能dir来检查它们,

>>> dir(p)# returns : ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'pick']

特殊功能或方法可以通过命名的方式来识别,它们总是以双重下划线’

‘开始,并以双重下划线’

‘结束,因为这种特殊的命名这些方法,它们是通常称为daunder方法(双 下划线= dunder)。因此,如果方法名称始于双重下划线,那么它很可能是一种特殊的方法。为什么不确定呢?这仅仅是因为python并没有阻止我们使用dunder语法定义自己的方法。还可以回到我们的游戏脚本。

>现在留给我们的一切都是让我们让我们的脚本知道如何确定赢家。如前所述,我将使用比较来评估赢家。
>

# comparison logicrock > scissorsscissors > paperpaper > rock

要实现此解决方案,我将添加一个字典并使用daunder_than方法。字典钥匙将是岩石,纸和剪刀的缩写。每个密钥的值将是钥匙可以击败的唯一另一个元素。>

请注意新的代码行,首先是选项字典,然后是__gt__方法定义。有了这些新的代码行,让我们看看我们的代码现在具有哪些新功能。

>

# create a rock instance>>> r = rps('r', 'rock')# create a paper instance>>> p = rps('p', 'paper')# create a scissors instance>>> s = rps('s', 'scissors')>>> print(r,p,s)# return : rock paper scissors>>> p > r # paper wins against rock# return : true>>> r > s # rock wins against scissors# return : true>>> s > p # scissors wins against paper# return : true>>> p >> p >> p < s >> p >= r paper wins or tie to rock# return : traceback (most recent call last):   file "", line 1, in  typeerror: '>=' not supported between instances of 'rps' and 'rps'

>仅通过添加__gt__ __ __gt__,我们的课堂实例就获得了魔法(有时称为魔术方法,我们可以看到原因)。通过实现daunder gt方法,我们的类实例现在与>和的否定。 对于≥符号,其特殊方法是__ge __(self,x),必须将其定义才能使我们的对象与≥符号合作。但是在这个程序中,我们可以没有它。 另一个缺失的部分是检查两个单独的纸张实例是否相等。>

>>> p1 = rps("p", "paper")>>> p2 = rps("p", "paper")>>> p3 = p1>>> p1 == p2# return : false>>> p1 == p3# return : true>>> id(p1)# return : 140197926465008>>> id(p2)# return : 140197925989440>>> id(p3)# return : 140197926465008>>> id(p1) == id(p3)# return : true>>> id(p2) == id(p1)# return false

>平等比较符号的默认操作是比较对象的id。 p1和p2是不同的类实例,恰好具有相同的属性,但其id有所不同,因此并不相等。当我们将变量分配给类实例时,我们将该变量点提高到实例的地址,这是我们对p3的观察到与p1相同的id。我们可以选择通过定义和实施自己的__eq __(自我,其他)方法来覆盖平等比较如何在我们的对象上起作用。但是对于此脚本,我将使用其选择属性比较两个实例。现在我们已经定义了我们的班级并知道了它的工作原理,现在我们准备看到python脚本的完整实现

将它们全部放在一起

>让我介绍您的代码。我们已经熟悉rps类定义。如果您还记得,我们的代码旨在允许计算机随机选择选择,这就是随机模块的目的。随机模块可提供选择功能,该功能允许从峰值对象中“随机”选择元素,例如python中的列表。在这种情况下,列表是option_list。由于我们的班级是与大写字母一起使用的,因此我们必须始终使用大写属性来初始化对象以进行选择属性。这就是为什么我们首先使用.upper()将用户的输入转换为上情况(第34行)的原因。我们的用户类型也有可能以“ q”为例,因此我们必须通过检查大写字符是否是option_list中有效选项的一部分来验证我们的用户输入。映射字典使我们能够在经过验证后将用户的输入快速转换为rps的相应实例。 estuatue_winner函数利用比较符号来确定获胜者。因为我们希望代码在循环中运行直到找到获胜者,所以我们使用一段时间循环,当找到获胜者时,evaluate_winner函数返回true,然后将打破循环并退出游戏。

这是运行代码的各种结果之一

>我们的python代码按预期运行,尽管可能需要添加一些改进或新功能。最重要的是,我们看到在班级定义中使用特殊方法如何给我们的代码带来更大的感觉。假设我们要采用不同的方法,例如使用嵌套if语句,我们的essuatue_winner方法看起来像这样的

>

def evaluate_winner(user_choice, comp_choice):    # check if user choice is 'r'    if user_choice == 'r':        # check if comp_choice is 'r'        if comp_choice == 'r':            # it is a tie            ...        elif comp_choice == 's':            # user wins            ...        else:          # computer wins          ...    if ...      # do the same for when user_choice is 's' and then for     # when user_choice is 'p'

>除冗长的代码外,这种方法的问题是,如果我们希望添加一个新元素,钻石可以击败岩石和剪刀,而不是纸(出于未知原因),我们的if语句将真正开始看起来很像尴尬的。而在我们的oop方法中,我们要做的就是修改符合

的选项

options = {"r" : ["s"], "p" : ["r"], "s" : ["p"], "d" : ["r", "s"]}

,然后我们将__gt__中的if语句更改为

>

def __gt__(self,x):        if x.pick in self.options[self.pick]:        return true    else:        return false

我们可以使语句缩短image of running the python script

def __gt__(self, x):   return True if x.pick in self.options[self.pick] else False

得出结论,您应该注意一些有关使用特殊方法的事情:>

>

您几乎没有(或从未)自己直接打电话给他们,让python为您打电话
>

立即学习“Python免费学习笔记(深入)”;

>
定义使用dunder命名语法的函数时,您应该认为python有一天可以定义这样的功能并赋予其不同的含义。这可能会破坏您的代码或以意外的方式行事

>

>您当然不必实现所有特殊方法。只是一对您真的确定需要的夫妇。请记住,简单胜于复杂。如果有一种更简单的方法,则应使用该方法

>要了解有关python数据模型的更多信息,我建议官方的python文档。

>我还建议阅读luciano ramalho

的fluent python>这是主题的第一部分,在下一部分中,我们将与操作员过载并使其使itable对象>

希望您喜欢这篇文章!

以上就是用Python数据模型编写Pythonic代码的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1356221.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月13日 19:39:10
下一篇 2025年12月13日 19:39:22

相关推荐

  • CSS mask属性无法获取图片:为什么我的图片不见了?

    CSS mask属性无法获取图片 在使用CSS mask属性时,可能会遇到无法获取指定照片的情况。这个问题通常表现为: 网络面板中没有请求图片:尽管CSS代码中指定了图片地址,但网络面板中却找不到图片的请求记录。 问题原因: 此问题的可能原因是浏览器的兼容性问题。某些较旧版本的浏览器可能不支持CSS…

    2025年12月24日
    900
  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 为什么设置 `overflow: hidden` 会导致 `inline-block` 元素错位?

    overflow 导致 inline-block 元素错位解析 当多个 inline-block 元素并列排列时,可能会出现错位显示的问题。这通常是由于其中一个元素设置了 overflow 属性引起的。 问题现象 在不设置 overflow 属性时,元素按预期显示在同一水平线上: 不设置 overf…

    2025年12月24日 好文分享
    400
  • 网页使用本地字体:为什么 CSS 代码中明明指定了“荆南麦圆体”,页面却仍然显示“微软雅黑”?

    网页中使用本地字体 本文将解答如何将本地安装字体应用到网页中,避免使用 src 属性直接引入字体文件。 问题: 想要在网页上使用已安装的“荆南麦圆体”字体,但 css 代码中将其置于第一位的“font-family”属性,页面仍显示“微软雅黑”字体。 立即学习“前端免费学习笔记(深入)”; 答案: …

    2025年12月24日
    000
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何解决本地图片在使用 mask JS 库时出现的跨域错误?

    如何跨越localhost使用本地图片? 问题: 在本地使用mask js库时,引入本地图片会报跨域错误。 解决方案: 要解决此问题,需要使用本地服务器启动文件,以http或https协议访问图片,而不是使用file://协议。例如: python -m http.server 8000 然后,可以…

    2025年12月24日
    200
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么我的特定 DIV 在 Edge 浏览器中无法显示?

    特定 DIV 无法显示:用户代理样式表的困扰 当你在 Edge 浏览器中打开项目中的某个 div 时,却发现它无法正常显示,仔细检查样式后,发现是由用户代理样式表中的 display none 引起的。但你疑问的是,为什么会出现这样的样式表,而且只针对特定的 div? 背后的原因 用户代理样式表是由…

    2025年12月24日
    200
  • inline-block元素错位了,是为什么?

    inline-block元素错位背后的原因 inline-block元素是一种特殊类型的块级元素,它可以与其他元素行内排列。但是,在某些情况下,inline-block元素可能会出现错位显示的问题。 错位的原因 当inline-block元素设置了overflow:hidden属性时,它会影响元素的…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 为什么使用 inline-block 元素时会错位?

    inline-block 元素错位成因剖析 在使用 inline-block 元素时,可能会遇到它们错位显示的问题。如代码 demo 所示,当设置了 overflow 属性时,a 标签就会错位下沉,而未设置时却不会。 问题根源: overflow:hidden 属性影响了 inline-block …

    2025年12月24日
    000
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 为什么我的 CSS 元素放大效果无法正常生效?

    css 设置元素放大效果的疑问解答 原提问者在尝试给元素添加 10em 字体大小和过渡效果后,未能在进入页面时看到放大效果。探究发现,原提问者将 CSS 代码直接写在页面中,导致放大效果无法触发。 解决办法如下: 将 CSS 样式写在一个单独的文件中,并使用 标签引入该样式文件。这个操作与原提问者观…

    2025年12月24日
    000
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200
  • 为什么我的 em 和 transition 设置后元素没有放大?

    元素设置 em 和 transition 后不放大 一个 youtube 视频中展示了设置 em 和 transition 的元素在页面加载后会放大,但同样的代码在提问者电脑上没有达到预期效果。 可能原因: 问题在于 css 代码的位置。在视频中,css 被放置在单独的文件中并通过 link 标签引…

    2025年12月24日
    100

发表回复

登录后才能评论
关注微信