Python 作为一种动态语言,提供了多种方法来实现相同的功能。这些选项在可读性、可维护性和性能方面可能有所不同。尽管我通常用 Python 编写的脚本是一次性的,但我现在有一个我正在从事的(学术)项目必须是可读的、可维护的并且性能相当好。由于我之前没有用 Python 进行过任何认真的编码,包括任何类型的分析,所以我需要帮助来决定上面提到的三个因素之间的平衡。
这是我正在处理的科学包中的一个模块的代码片段。它是一个具有非常基本骨架结构的 n 叉树类。这是在考虑继承和子类的情况下编写的。
注意:在下面的代码中,树与节点相同。每棵树都是同一类 Tree 的实例。
class Tree(object):
def __init__(self, parent=None, value=None):
self.parent = parent
self.value = value
self.children = set()
下面的两个函数属于此类(以及许多其他函数)
def isexternal(self):
"""Return True if this is an external tree."""
return not bool(self.children)
def isleaf(self):
"""Return True if this is a leaf tree."""
return not bool(self.children)
这两个函数做着完全相同的事情——它们只是两个不同的名称。那么,为什么不将其更改为:
def isleaf(self):
"""Return True of this is a leaf tree."""
return self.isexternal()
我的疑问是这些:
我读到 Python 中的函数调用相当昂贵(为每次调用创建新堆栈),但我不知道如果一个函数依赖于另一个函数是好事还是坏事。它将如何影响可维护性。这在我的代码中多次发生,我从另一个方法调用一个方法以避免代码重复。这样做是不好的做法吗?
这是同一类中此代码重复场景的另一个示例:
def isancestor(self, tree):
"""Return True if this tree is an ancestor of the specified tree."""
return tree.parent is self or (not tree.isroot()
and self.isancestor(tree.parent))
def isdescendant(self, tree):
"""Return True if this tree is a descendant of the specified tree."""
return self.parent is tree or (not self.isroot()
and self.parent.isdescendant(tree))
我可以改为:
def isdescendant(self, tree):
"""Return True if this tree is a descendant of the specified tree."""
return tree.isancestor(self)
最佳答案
非常从广义上讲,有两种类型的优化:宏观优化和微观优化。宏观优化包括您选择的算法、决定不同的数据结构等。 会对性能产生重大影响的事情,如果您改变主意,通常会对您的代码库产生巨大的链式 react 。从具有线性 O(n) 的数据结构切换到具有常量 O(1) 插入的数据结构可能是一个巨大的胜利,并且非常值得为此付出代价。添加缓存可能会将慢狗算法变成快如闪电的算法。
微优化是诸如省略或内联函数调用、删除或添加变量、为非常短的窗口缓存计算结果、展开循环等。通常,您应该忘记这些类型的优化和重点关于代码的可读性和可维护性。微优化的效果太小,不值得。
分析代码后,您应该只考虑这些类型的更改。如果您可以确定一个可以从这种优化中受益的关键循环,并且您的分析确认它会,并且您进行更改并验证改进与另一轮分析的工作 - 然后 你应该微优化。
但在那之前,不要为小事担心。
def isdescendant(self, tree):
"""Return True if this tree is a descendant of the specified tree."""
return tree.isancestor(self)
我绝对会推荐这种类型的代码重用。它清楚地表明 isdescendant 是 isancestor 的倒数。它确保两个函数以相同的方式工作,因此您不会无意中在一个函数中引入错误,而在另一个函数中引入错误。
def isleaf(self):
"""Return True of this is a leaf tree."""
return self.isexternal()
在这里我会问自己 isleaf 和 isexternal 在概念上是否相同。忽略它们的实现方式相同,它们在逻辑上是否相同?如果是这样,我会让一个人调用另一个人。如果只是碰巧他们有相同的实现,我可能会复制代码。您能想象这样一种场景,您想要更改一个功能而不是另一个吗?这将指向重复。
关于python - 代码重复和性能之间的权衡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31688034/
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur