我知道python函数默认是虚拟的.假设我有这个:
class Foo:
def __init__(self, args):
do some stuff
def goo():
print "You can overload me"
def roo():
print "You cannot overload me"
Run Code Online (Sandbox Code Playgroud)
我不希望他们能够做到这一点:
class Aoo(Foo):
def roo():
print "I don't want you to be able to do this"
Run Code Online (Sandbox Code Playgroud)
有没有办法防止用户超载roo()?
Mar*_*wis 38
您可以使用元类:
class NonOverridable(type):
def __new__(self, name, bases, dct):
if bases and "roo" in dct:
raise SyntaxError, "Overriding roo is not allowed"
return type.__new__(self, name, bases, dct)
class foo:
__metaclass__=NonOverridable
...
Run Code Online (Sandbox Code Playgroud)
每当创建子类时,都会调用元类型的new ; 如果您出现,这将导致错误.只有在没有基类的情况下,它才会接受roo的定义.
通过使用注释声明哪些方法是最终的,您可以使方法更加花哨; 然后,您需要检查所有基础并计算所有最终方法,以查看是否有任何基础被覆盖.
这仍然不能阻止某人在定义之后将方法修补到类中; 您可以尝试通过使用自定义词典作为类的字典来捕获这些(这可能不适用于所有Python版本,因为类可能要求类字典具有精确的dict类型).
Tag*_*gar 36
Python 3.8(2019 年 10 月发布)final为输入添加了限定符。
一个final限定符被添加到类型模块——以final装饰器和最终类型注释的形式——用于三个相关目的:
from typing import final
class Base:
@final
def foo(self) -> None:
...
class Derived(Base):
def foo(self) -> None: # Error: Cannot override final attribute "foo"
# (previously declared in base class "Base")
...
Run Code Online (Sandbox Code Playgroud)
它符合您的要求,现在由核心 Python 支持。
查看PEP-591了解更多细节。
S.L*_*ott 10
由于Python有猴子修补,你不仅可以做任何"私人".即使你可以,有人仍然可以在新版本的方法函数中进行monkeypatch.
您可以将此类名称用作"不要靠近"警告.
class Foo( object ):
def _roo( self ):
"""Change this at your own risk."""
Run Code Online (Sandbox Code Playgroud)
这是通常的做法.每个人都可以阅读你的来源.他们被警告了.如果他们大胆地去了他们被警告不去的地方,他们就会得到他们应得的.它不起作用,你无法帮助他们.
您可以尝试使用"私有"方法调用的内部类和"隐藏"实现模块来故意使用此方法.但是......每个人都有你的来源.你不能阻止任何事情.你只能告诉人们他们行为的后果.
def non_overridable(f):
f.non_overridable = True
return f
class ToughMeta(type):
def __new__(cls, name, bases, dct):
non_overridables = get_non_overridables(bases)
for name in dct:
if name in non_overridables:
raise Exception ("You can not override %s, it is non-overridable" % name)
return type.__new__(cls, name, bases, dct)
def get_non_overridables(bases):
ret = []
for source in bases:
for name, attr in source.__dict__.items():
if getattr(attr, "non_overridable", False):
ret.append(name)
ret.extend(get_non_overridables(source.__bases__))
return ret
class ToughObject(object):
__metaclass__ = ToughMeta
@non_overridable
def test1():
pass
# Tests ---------------
class Derived(ToughObject):
@non_overridable
def test2(self):
print "hello"
class Derived2(Derived):
def test1(self):
print "derived2"
# --------------------
Run Code Online (Sandbox Code Playgroud)