- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在摆弄继承,发现了一种对我来说似乎很奇怪的行为——也就是说,有时我可以重写父装饰器函数(用于验证),但有时我不能,而且我无法理解为什么或者有什么区别。
文字快速演练——我有一个人对象,我想将其子类化为更特定的人对象。更具体的一个将有一个附加字段“舞蹈”,并且对前一个字段“名称”将具有不同的验证规则。
这是我有效的基本案例:
# Define the validation wrapper
def ensure(name, validate, doc=None):
def decorator(Class):
privateName = "__" + name
def getter(self):
return getattr(self, privateName)
def setter(self, value):
validate(name, value)
setattr(self, privateName, value)
setattr(Class, name, property(getter, setter, doc=doc))
return Class
return decorator
# Define the not string validation
def is_not_str(name, value):
if isinstance(value, str):
raise ValueError("{} cannot be a string.".format(name))
# Chosen to be exact opposite of above---demonstrating it's possible to reverse.
def is_str(name, value):
if not isinstance(value, str):
raise ValueError("{} must be a string.".format(name))
@ensure("name", is_str)
@ensure("url", is_str)
class Person(object):
def __init__(self,s):
self.name = s.get('name',{})
self.url = s.get('url','')
def __str__(self):
return "Person({{'name':'{}','url':'{}'}})".format(self.name, self.url)
def __repr__(self):
return str(self)
@ensure("name", is_not_str) # require a number rather than a Name() object.
class Crazyperson(Person):
def __init__(self,s):
super(Crazyperson,self).__init__(s) # idiom to inherit init
self.dance = s.get('dance') # add new param.
bill = Person({"name":"bill",
"url":"http://www.example.com"})
fred = Crazyperson({"name":1,
"url":"http://www.example.com",
"dance":"Flamenco"})
这很好用。因此,第一个对象 bill 的创建方式使得验证 is_str 成功。如果你尝试在那里输入一个数字,就会失败。第二个对象同样接受非字符串,因此 fred 创建成功。
现在,这是它崩溃的情况,我想了解......
def is_Name(name, value):
if not isinstance(value, dict) and not isinstance(value,Name):
raise ValueError("{} must be a valid Name object".format(name))
# new object that will be a non-string type of name.
@ensure("firstname", is_str)
@ensure("lastname", is_str)
class Name(object):
def __init__(self,s):
self.firstname = s.get('firstname','')
self.lastname = s.get('lastname')
def __str__(self):
return "Name({{'firstname':'{}','lastname':'{}' }})".format(self.firstname, self.lastname)
def __repr__(self):
return str(self)
@ensure("name", is_Name) # require it as the default for the base class
@ensure("url", is_str)
class Person(object):
def __init__(self,s):
self.name = Name(s.get('name',{}))
self.url = s.get('url','')
def __str__(self):
return "Person({{'name':'{}','url':'{}'}})".format(self.name, self.url)
def __repr__(self):
return str(self)
@ensure("name", is_str) # require a number rather than a Name() object.
class Crazyperson(Person):
def __init__(self,s):
super(Crazyperson,self).__init__(s)
self.name = s.get('name','') # THIS IS THE KEY
self.dance = s.get('dance')
bill = Person({"name":{"firstname":"Bill", "lastname":"billbertson"},
"url":"http://www.example.com"})
fred = Crazyperson({"name":"Fred",
"url":"http://www.example.com",
"dance":"Flamenco"})
在这种情况下,Crazyperson 失败了。该错误表明 __init__
中的 is_Name
验证函数仍在应用:
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
File "<stdin>", line 4, in __init__
File "<stdin>", line 5, in __init__
File "<stdin>", line 5, in __init__
AttributeError: 'str' object has no attribute 'get'
看起来它已经在字符串名称“Fred”上调用了 Name
初始值设定项:Name(s.get('name',{}))
。
但似乎不可能,因为在前面的示例中,我能够删除完全矛盾的验证(is_str
与 is_not_str
)。为什么这相反较少但失败较多?在第一种情况下,它没有同时应用 is_str
和 is_not_str
,为什么现在/同时应用 is_Name
和 is_str
具有看似相同的语法?
我的问题是:第一种方法与第二种方法有什么不同,导致它成功?我试图在这里隔离变量,但不明白为什么我可以撤消场景一中从父类继承的包装验证器,但不能做场景二中看起来类似的事情。似乎唯一有意义的区别是它是一个对象而不是字符串。
(我知道,更好的架构方法来做到这一点是有第三个更抽象的父类,没有需要更改的验证规则——两种人都会继承它。但我也明白我我应该能够更改子类中的方法,所以我想至少了解一个成功和另一个失败的原因之间的区别。)
最佳答案
在您的第二个设置中,is_Name
函数未应用。您正在创建Name
对象,无论如何,在 __init__
方法:
class Person(object):
def __init__(self,s):
self.name = Name(s.get('name',{}))
self.url = s.get('url','')
注意 self.name = Name(...)
在那儿排队。
在 Crazyperson.__init__()
您调用父方法:
def __init__(self,s):
super(Crazyperson,self).__init__(s)
self.dance = s.get('dance')
传递s
至Person.__init__()
这会创建一个 Name()
对象。
所以当你创建fred
时与 fred = Crazyperson({"name":"Fred", ...})
你正在路过name
设置为字符串 'Fred'
至Name.__init__()
,它需要一个字典:
class Name(object):
def __init__(self,s):
self.firstname = s.get('firstname','')
self.lastname = s.get('lastname')
这就是您的代码失败的地方:
>>> 'Fred'.get('firstname', '')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'get'
仅设置name
上Person
如果没有self.name
已设置:
class Person(object):
def __init__(self,s):
if not hasattr(self, 'name')
self.name = Name(s.get('name', {}))
self.url = s.get('url','')
并设置name
第一 Crazyperson
:
def __init__(self,s):
self.name = s.get('name', 0)
self.dance = s.get('dance')
super(Crazyperson,self).__init__(s)
关于python - 重写修饰的子类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17597776/
我在使用 lambda 表达式时遇到问题,该表达式用于自定义过滤来自 DataGridView 的数据。 这是表达式: private static Expression> ExpressionLon
我想使用装饰器模式扩展 basic_streambuf 对象的行为。这就是我目前得到的: template class forwarding_basic_streambuf : boost::
我正在编写一个 Backbone 应用程序,我想编写一个经过身份验证的装饰器,我可以用它来装饰路由器类中的方法(路由)列表。 所以我有一个带有几种方法的路由器,并尝试过类似的方法。但是,当我调用我想要
我想重写 alert() Javascript 函数,同时保留它的“聚焦”行为。即,自定义方面,同时将焦点带到打开弹出窗口的浏览器选项卡。 最佳答案 无法直接自定义/装饰 JavaScript 警报框
我们如何在 jquery mobile 中实现事件行为内部的 touch up。 我希望它的行为与 native ios 按钮完全相同。我们可以点击并按住点击并在按钮内移动手指只有当我在按钮内释放时才
我正在尝试覆盖模块(connect-mongo)中的类。该模块的工作原理大致如下: 在server.js中: const session = require('express-session'); c
我希望使用托管代码在非托管 C++ DLL 上加载库,然后在已损坏的外部函数上调用 GetProcAddress。我的问题是,您从 C++ 编译器获得的错位名称是否具有确定性?即:如果原始签名未更改,
为什么我不能使用 @staticmethod 装饰器使类的 __call__ 方法静态化? class Foo(object): @staticmethod def bar():
我有一个小的 Delphi 10.3.3 应用程序,它有一些文本编辑功能,使用用户输入文本的 TMemo。 我正在尝试包含一些格式选项,如本网站提供的内容: http://qaz.wtf/u/conv
这是我关于使用 Swift 运行的 iOS 应用程序的情况。 我有一个下载按钮,触摸后即可开始下载文件: @IBAction func downloadButtonPressed() { if
我有一个 View ,我需要检测一个属性是否用隐藏输入装饰。 我的属性(property)被定义为: [HiddenInput(DisplayValue = false)] public string
我在我的 Qt 应用程序中绘制线和点,但在 QPainter 中似乎存在缩放错误时遇到了问题。我的线条工作得很好,但点会受到某些缩放转换的影响,尽管笔被设置为“化妆品”。最让我困扰的是似乎只有一个轴(
我在 Eclipse 中遇到 Java 语法着色问题。我正在尝试更改 Eclipse 中 JUST java 修饰符的文本颜色(如公共(public)、 protected 、私有(private))
我在站点上有一些限制区域,我想为其指定 login_required 装饰器。但是我想在主 urls.py 中每次包含一次,而不是包含 urls.py 中的每个单独的 url 所以代替: /priva
这个建议似乎很有意义,因为该方法中没有使用 self,但现在我很好奇: 这是对 CBV 的疏忽吗?用户应该手动装饰每个 @staticmethod? Django 中是否已经有一些代码可以自动使所有
python 3.3:我可以装饰一个函数来忽略所有与命名参数不匹配的位置参数吗? import functools def ignore_star_args(): def wrapper(fu
我是一名优秀的程序员,十分优秀!