- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试编写从类创建类而不修改原始类的函数。
简单的解决方案(基于 this answer )
def class_operator(cls):
namespace = dict(vars(cls))
... # modifying namespace
return type(cls.__qualname__, cls.__bases__, namespace)
工作正常,除了 type
本身:
>>> class_operator(type)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: type __qualname__ must be a str, not getset_descriptor
在 Python 3.2-Python 3.6 上测试。
(我知道在当前版本中修改 namespace
对象中的可变属性会改变原始类,但事实并非如此)
即使我们从 namespace
中删除 __qualname__
参数(如果有的话)
def class_operator(cls):
namespace = dict(vars(cls))
namespace.pop('__qualname__', None)
return type(cls.__qualname__, cls.__bases__, namespace)
结果对象的行为与原始类型
不同
>>> type_copy = class_operator(type)
>>> type_copy is type
False
>>> type_copy('')
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: descriptor '__init__' for 'type' objects doesn't apply to 'type' object
>>> type_copy('empty', (), {})
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: descriptor '__init__' for 'type' objects doesn't apply to 'type' object
谁能解释一下 Python 内部的什么机制可以防止复制 type
类(以及许多其他内置类)。
最佳答案
这里的问题是 type
有一个 __qualname__
在其 __dict__
,这是一个属性(即 descriptor )而不是字符串:
>>> type.__qualname__
'type'
>>> vars(type)['__qualname__']
<attribute '__qualname__' of 'type' objects>
并尝试将非字符串分配给 __qualname__
一个类的抛出异常:
>>> class C: pass
...
>>> C.__qualname__ = 'Foo' # works
>>> C.__qualname__ = 3 # doesn't work
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign string to C.__qualname__, not 'int'
这就是为什么有必要删除 __qualname__
来自 __dict__
.
至于你的type_copy
的原因不可调用:这是因为 type.__call__
拒绝任何不是 type
子类的东西.对于 3 参数形式都是如此:
>>> type.__call__(type, 'x', (), {})
<class '__main__.x'>
>>> type.__call__(type_copy, 'x', (), {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor '__init__' for 'type' objects doesn't apply to 'type' object
以及单参数形式,它实际上只适用于 type
作为它的第一个参数:
>>> type.__call__(type, 3)
<class 'int'>
>>> type.__call__(type_copy, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type.__new__() takes exactly 3 arguments (1 given)
这不容易规避。修复 3-argument 形式很简单:我们将副本设为 type
的空子类。 .
>>> type_copy = type('type_copy', (type,), {})
>>> type_copy('MyClass', (), {})
<class '__main__.MyClass'>
但是type
的单参数形式更麻烦,因为它只有在第一个参数是 type
时才有效.我们可以实现自定义 __call__
方法,但是那个方法必须写在元类中,也就是type(type_copy)
将不同于 type(type)
.
>>> class TypeCopyMeta(type):
... def __call__(self, *args):
... if len(args) == 1:
... return type(*args)
... return super().__call__(*args)
...
>>> type_copy = TypeCopyMeta('type_copy', (type,), {})
>>> type_copy(3) # works
<class 'int'>
>>> type_copy('MyClass', (), {}) # also works
<class '__main__.MyClass'>
>>> type(type), type(type_copy) # but they're not identical
(<class 'type'>, <class '__main__.TypeCopyMeta'>)
type
有两个原因很难复制:
int
,你会遇到类似的问题。或 str
.事实 type
是自身的实例:
>>> type(type)
<class 'type'>
这通常是不可能的。它模糊了类和实例之间的界限。它是实例和类属性的困惑堆积。这就是为什么 __qualname__
当作为 type.__qualname__
访问时是一个字符串但是当作为 vars(type)['__qualname__']
访问时是一个描述符.
如您所见,不可能完美复制 type
.每个实现都有不同的权衡。
简单的解决方案是创建 type
的子类,它不支持单参数 type(some_object)
调用:
import builtins
def copy_class(cls):
# if it's a builtin class, copy it by subclassing
if getattr(builtins, cls.__name__, None) is cls:
namespace = {}
bases = (cls,)
else:
namespace = dict(vars(cls))
bases = cls.__bases__
cls_copy = type(cls.__name__, bases, namespace)
cls_copy.__qualname__ = cls.__qualname__
return cls_copy
精心设计的解决方案是制作自定义元类:
import builtins
def copy_class(cls):
if cls is type:
namespace = {}
bases = (cls,)
class metaclass(type):
def __call__(self, *args):
if len(args) == 1:
return type(*args)
return super().__call__(*args)
metaclass.__name__ = type.__name__
metaclass.__qualname__ = type.__qualname__
# if it's a builtin class, copy it by subclassing
elif getattr(builtins, cls.__name__, None) is cls:
namespace = {}
bases = (cls,)
metaclass = type
else:
namespace = dict(vars(cls))
bases = cls.__bases__
metaclass = type
cls_copy = metaclass(cls.__name__, bases, namespace)
cls_copy.__qualname__ = cls.__qualname__
return cls_copy
关于python - 复制内置类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50175903/
我试图在 (C) Python 源代码中找到内置 in 运算符的实现。我在内置函数源代码中搜索过,bltinmodule.c ,但找不到此运算符的实现。我在哪里可以找到这个实现? 我的目标是通过扩展此
我们正在开发一个 shell(学校项目)。我们不理解一种行为。为什么内置函数在重定向时不起作用? 喜欢 cd - | command 不改变目录。 或 export NAME=VALUE | comm
有人问有关如何对列表进行排序的问题。从基本List.Sort()到List.OrderBy()有几种方法。最可笑的是自己动手的SelectionSort。我迅速将其否决,但这使我思考。应用于列表的
我正在尝试使用 C 中内置的 qsort 函数对结构进行排序 typedef struct abc{ long long int fir; long long int sec; }abc; 在
我觉得有一些内置的东西。如果对象为空,我想要默认值(或者特别是 0,我只使用十进制/整数)。是否有编写此函数的内置方法? static int GetDecimalFromObject(object
Java 是否有用于生成和解析文档的内置 XML 库?如果不是,我应该使用哪个第三方? 最佳答案 Sun Java 运行时附带 Xerces 和 Xalan 实现,它们提供解析 XML(通过 DOM
我对 python 的“all”和生成器有以下问题: G = (a for a in [0,1]) all(list(G)) # returns False - as I expected 但是:
我有一些使用 gcc 内部函数的代码。我想包含代码以防缺少内在函数。我该怎么做? #ifdef __builtin_ctzll 不起作用。 最佳答案 使用最新版本的 clang,现在可以使用 __ha
人们常说应该在本地重新声明(某些)Lua 函数,因为这样可以减少开销。但这背后的确切规则/原则是什么?我怎么知道哪些功能应该完成,哪些是多余的?还是应该为每个功能完成,甚至是您自己的功能? 不幸的是,
我想实现以下功能: TestClass values 接受任意数量的 NewClass 对象 只有 NewClass 对象没有完全相同的属性值被添加到TestClass.values 我想出了这个:
我正在尝试编写一个存储过程(使用 SQL Server Management Studio 2008 R2)以从表中检索最大测量值。这似乎是一件容易的事,所以我写了一个简短的存储过程来获取 MAX。但
我刚写了我的第一个Electron应用程序。现在,我正在尝试通过electron-packager构建它。我的package.json看起来像这样: { "name": "pixelcast",
我正在寻找在 WPF 应用程序中使用的“安全”字体系列列表 - 应该安装在所有能够运行 WPF 的客户端机器上的字体系列。 Silverlight 有一个明确定义的列表( listed on MSDN
好吧,(在写了几次之后)发现System.Windows.Controls命名空间中已经有一个BooleanToVisibilityConverter,这真是一个惊喜。 可能还有更多这样隐藏的节省时间
在我的 gradle 构建文件中,我有以下插件 block plugins { `java-library` jacoco checkstyle } 这些都没有指定版本,但一切
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 3 年前。 Improve this ques
10 implementations String#reverse 已根据每个浏览器进行分析。 自 2011 年以来已对这些实现进行了解释。 当 ES6 出现时,有很多代码变得更加优雅和性能。 关于
在 Julia 包 BenchmarkTools 中,有一些像 @btime、@belapse 这样的宏对我来说似乎是多余的,因为 Julia 内置了@time、@elapse 宏。在我看来,这些宏服
我正在尝试编写一个简单的 LLVM 通行证,其目标如下: 查找所有 call指示。 在被调用函数中插入我编写的外部函数。 例如,考虑我有以下示例程序: #include #include int
我理解 'a) -> (rhs:'a -> 'a) -> 'a 在我感兴趣的情况下,我经常发现自己想要类似 (lhs:'a -> 'b) -> (rhs:'c -> 'b) -> 'b 的东西在侧面
我是一名优秀的程序员,十分优秀!