我想提供一个可以在Python 2.7类对象上使用的方法,但不会污染其实例的属性名称空间。有没有办法做到这一点?
select t1.*
from tblItemsOrdered t1
inner join (
select t1.itemNumber, max(t1.PONumber) as max_PONumber
from tblItemsOrdered t1
inner join (
SELECT itemNumber, Max(OrderDate) as Max_OrderDate
FROM tblItemsOrdered
GROUP BY itemNumber
) t2 on t1.itemNumber = t2.itemNumber
and t1.OrderDate = t2.Max_OrderDate
group by t1.itemNumber
) t2 on t1.itemNumber = t2.itemNumber
and t1.PONumber = t2.max_PONumber;
答案 0 :(得分:4)
ugh
不在命名空间中:
>>> foo.__dict__
{}
但属性查找的规则会回退到缺少名称的实例类型。您可以覆盖Foo.__getattribute__
以阻止此操作。
class Foo(object):
@classmethod
def ugh(cls):
return 33
def __getattribute__(self, name):
if name == 'ugh':
raise AttributeError("Access to class method 'ugh' block from instance")
return super(Foo,self).__getattribute__(name)
这会产生:
>>> foo = Foo()
>>> foo.ugh()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "tmp.py", line 8, in __getattribute__
raise AttributeError("Access to class method 'ugh' block from instance")
AttributeError: Access to class method 'ugh' block from instance
>>> Foo.ugh()
33
您必须使用__getattribute__
,这是在任何属性访问时无条件调用,而不是__getattr__
,只有在正常查找(包括检查类型的命名空间)失败后才会调用它。{/ p >
答案 1 :(得分:4)
您可以继承classmethod描述符:
class classonly(classmethod):
def __get__(self, obj, type):
if obj: raise AttributeError
return super(classonly, self).__get__(obj, type)
这就是它的表现:
class C(object):
@classonly
def foo(cls):
return 42
>>> C.foo()
42
>>> c=C()
>>> c.foo()
AttributeError
这样去掉了描述符调用(相反,它是由__getattribute__
的默认实现调用的):
>>> C.__dict__['foo'].__get__(None, C)
<bound method C.foo of <class '__main__.C'>>
>>> C.__dict__['foo'].__get__(c, type(c))
AttributeError
必读:Data Model — Implementing Descriptors和Descriptor HowTo Guide。
答案 2 :(得分:2)
是的,您可以在元类中创建方法。
class FooMeta(type):
# No @classmethod here
def ugh(cls):
return 33
class Foo(object):
__metaclass__ = FooMeta
Foo.ugh() # returns 33
Foo().ugh() # AttributeError
请注意,元类是一种强大功能,如果不必要,不鼓励使用它们。特别是,如果父类具有不同的元类,则多重继承需要特别小心。
答案 3 :(得分:1)
Python有quasi-private variables使用名称修改来减少意外访问。形式为__name
的方法和对象变量将转换为_ClassName__name
。 Python在编译类的方法时会自动更改名称,但不会更改子类的名称。
我可以在类
中使用私有方法>>> class A(object):
... def __private(self):
... print('boo')
... def hello(self):
... self.__private()
...
>>>
>>> A().hello()
boo
但不在课外
>>> A().__private()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute '__private'
>>>
或在子类中
>>> class B(A):
... def hello2(self):
... self.__private()
...
>>>
>>> B().hello()
boo
>>> B().hello2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in hello2
AttributeError: 'B' object has no attribute '_B__private'