切勿在生产代码中使用reflection! 那Python怎么样?

我写了C#,而来自高处的口头禅似乎“永远不会在生产代码中使用reflection”。 我已将它用于测试代码,但从未在野外运行过。 所有的论点看起来都是合理的,并且总是有办法通过添加另一层抽象或设计模式或其他来做到这一点。

现在我开始编写一些严肃的Python代码,我想知道是否适用相同的原则。 似乎python的设计考虑了reflection。 模块和类将成员存储在易于访问的字典中。 Django的模型的Meta类,例如将字符串作为引用成员。

我可以在Python中编写C#/ Java,但我真的不想这样做。 我仍然坚信所谓的语言“没有反思”。 Python的方式根本不同吗?

作为一种动态语言,Python与静态类型语言根本不同,所以一切都在其中反映:-) 在生产代码 (对于静态语言)中从不使用reflection对我来说似乎有点极端。

我认为c#中的“生产代码中没有反映”是不正确的。
reflection通常允许程序员做其他事情不可能完成的事情。
我会说“在生产代码中没有反映非公开成员”和“谨慎使用反思!” 如果使用不当,可能会失去性能。 正确使用可以让你获得性能(只考虑静态reflection)不要使用reflection来大规模调用代码。
而Python则是一种动态语言。 所有概念都不同。 正常性(以及正确的方法)是使用您正在谈论的技术。

是的,在这方面,Python开发基本上不同的。

C#/ Java中的反思是指运行时能够了解正在运行的代码,并根据该信息做出决策。

由于Python使用动态类型,任何类型的发现都被委托给运行时而不是编译时,所以基本上这意味着, 任何 Python程序必须使用reflection才能工作,只有它不被称为reflection,它被称为运行程序:)
此外,Python哲学包含了执行的动态特性,因此您应该毫不犹豫地将它用于您的优势。

PS虽然应该避免在紧密循环中使用reflection,并且应该意识到reflection慢一到两个数量级,但是当它是正确的工具时,不应该害怕使用它。

IMO之所以避免在生产代码中使用reflection是因为reflection可能会使代码难以维护和调试。

反思是非常先进和强大的技术。 但它很慢。 你可以使用reflection,但不能经常使用reflection。 因此,CLR开发人员为.NET 4.0添加了一个更酷的类型 – 动态类型 。 我强烈建议您参考一些文档或书籍以获取更多信息。 Fe CLR通过C#。

 dynamic a = SomeFooInterface.GetsomeObjectWithUnknownInterface(); // returns object, for example, from another assembly. or some unknown instance. // But you know that there is method int GetValue() inside. // So you can call this method without any casts! int myValue = a.GetValue(); // This method is much faster then reflection! 

通过C#CLR:

在程序运行之前,程序还必须对其不知道的信息采取行动。 虽然您可以使用类型安全的编程语言(如C#)与此信息进行交互,但语法往往很笨拙,特别是因为您倾向于使用字符串进行大量工作,并且性能也受到了阻碍。 如果您正在编写一个纯C#应用程序,那么您使用运行时确定的信息的唯一场合就是使用reflection(在第23章中讨论)。 但是,许多开发人员还使用C#与未在C#中实现的组件进行通信。 其中一些组件可能是.NET动态语言,如Python或Ruby ,或支持IDispatch接口的COM对象(可能用本机C或C ++实现),或HTML文档对象模型(DOM)对象(使用各种语言和技术)。 在构建Microsoft Silverlight应用程序时,与HTML DOM对象进行通信特别有用。 为了使开发人员更容易使用reflection或与其他组件通信,C#编译器为您提供了一种将表达式类型标记为动态的方法。 您还可以将表达式的结果放入变量中,并将变量的类型标记为动态。 然后,可以使用此动态表达式/变量来调用诸如字段,属性/索引器,方法,委托和一元/二进制/转换运算符之类的成员。 当您的代码使用动态表达式/变量调用成员时,编译器会生成描述所需操作的特殊IL代码。 此特殊代码称为有效负载。 在运行时,有效负载代码根据动态表达式/变量现在引用的对象的实际类型确定要执行的确切操作。