Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 限制属性的创建/设置_Python_Python 3.x - Fatal编程技术网

Python 限制属性的创建/设置

Python 限制属性的创建/设置,python,python-3.x,Python,Python 3.x,如何在类/子类之外限制属性的创建 __all__ = ["Employee","Salary","Wage"] ################################################################################################## class Person(object): def __init__(self,fname,lname,gender): self.__setfname(fname)

如何在类/子类之外限制属性的创建

__all__ = ["Employee","Salary","Wage"]
##################################################################################################
class Person(object):
    def __init__(self,fname,lname,gender):
        self.__setfname(fname) # "We are all adults." vs. "Name mangling."
        self.__setlname(lname)
        self.__setgender(gender)
    def __setfname(self,fname): self.__fname = fname
    def __setlname(self,lname): self.__lname = lname
    def __setgender(self,gender): self.__gender = gender
    def getname(self): return "{} {}".format(self.__fname,self.__lname)
    def getformattedname(self):
        if(self.__gender.lower() == "m"):
            return "Mr. {}".format(self.getname())
        if(self.__gender.lower() == "f"):
            return "Ms. {}".format(self.getname())
        if(self.__gender.lower() == ""):
            return "{}".format(self.getname())
class Payment(object):
    def __init__(self,amount,currency="INR"): # currency="USD"
        self.__setamount(amount)
        self.__setcurrency(currency)
    def __setamount(self,amount): self.__amount = amount
    def __setcurrency(self,currency): self.__currency = currency
    def getamount(self): return "{}".format(self.__amount)
    def getformattedamount(self): return "{} {}".format(self.getamount(),self.__currency)
##################################################################################################
##################################################################################################
class Employee(Person):
    def __init__(self,fname,lname,gender): super(Employee,self).__init__(fname,lname,gender)
    def __str__(self): return self.getformattedname()
class Salary(Payment):
    def __init__(self,amount,currency="INR"): super(Salary,self).__init__(amount,currency)
    def __str__(self): return self.getformattedamount()
class Wage(Payment):
    def __init__(self,amount,currency="INR"): super(Wage,self).__init__(amount,currency)
    def __str__(self): return self.getformattedamount()
##################################################################################################

我同意这一点:

e1._Person__fname = "Spam"
s1._Payment__amount = "1000000000000000"
但以下代码创建了新属性:

e1.fname = "New"
s1.amount = -10
class Person(object):
    __slots__ = ('_Person__fname', '_Person__lname', '_Person__gender')
    ...

class Employee(Person):
    __slots__ = () # All subclasses also need define __slots__ 
    ...

e1._Person__fname = "Spam"  # Fine
e1.fname = "New"            # AttributeError: 'Employee' object has no attribute 'fname'


您可以这样做:

class A:
    def __setattr__(self, attr, val):
        try :
            class_name, varname = attr.split('__', 1)
            if class_name == '_' + self.__class__.__name__:
                self.__dict__[attr] = val
            else:
                raise AttributeError
        except ValueError:
            raise AttributeError
演示:

>>> %run so.py
>>> a = A()
>>> a._A__foo = 1
>>> a._A__bar = 2
>>> a._A = 2
Traceback (most recent call last):
  File "<ipython-input-28-eace128dbfc5>", line 1, in <module>
    a._A = 2
  File "/home/monty/py/so.py", line 10, in __setattr__
    raise AttributeError
AttributeError

>>> a.A__bar = 2
Traceback (most recent call last):
  File "<ipython-input-29-57210782cd6a>", line 1, in <module>
    a.A__bar = 2
  File "/home/monty/py/so.py", line 8, in __setattr__
    raise AttributeError
AttributeError

>>> a._A__spam = 3
>>> a.__dict__
{'_A__foo': 1, '_A__spam': 3, '_A__bar': 2}
>>%运行so.py
>>>a=a()
>>>a.。u a_uufoo=1
>>>a.。\u a\u条=2
>>>a._a=2
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
a、 _a=2
文件“/home/monty/py/so.py”,第10行,在__
提高属性错误
属性错误
>>>a.a____bar=2
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
a、 a_uuu条=2
文件“/home/monty/py/so.py”,第8行,在__
提高属性错误
属性错误
>>>a.。\u a\u垃圾邮件=3
>>>格言__
{u-A-u-foo':1,'u-A-u-spam':3,'u-A-u-bar':2}
我们可以,尽管
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

e1.fname = "New"
s1.amount = -10
class Person(object):
    __slots__ = ('_Person__fname', '_Person__lname', '_Person__gender')
    ...

class Employee(Person):
    __slots__ = () # All subclasses also need define __slots__ 
    ...

e1._Person__fname = "Spam"  # Fine
e1.fname = "New"            # AttributeError: 'Employee' object has no attribute 'fname'

请注意,使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
时,实例的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

class Foo(object):
    def __init__(self):
        self._amount = 0

    @property
    def amount(self):
        return self._amount


f = Foo()
print f.amount  # ok
f.amount = 100  # error

不要试图这样做。别人对你的课做什么不关你的事。您应该记录哪些属性应该可用,如果有人想滥用它,那是他们的问题,而不是你的问题


“我们在这里都是同意的成年人”是python的哲学。

为什么额外的属性是一个问题?我使用
\uu
前缀使属性私有化。我不希望这些“名称”(属性)在类外可以访问。(y)@“别人对你的类做什么不关你的事。”但是。。。如果其他人开始滥用这些属性,使模型/数据库开始受到影响,这是我的事。我和Daniel的观点相同。如果你买了一辆车,并以这样一种方式操纵刹车,使其不再工作,这几乎不是汽车制造商的问题,而是你自己的问题。如果您使用某个库的未记录功能,而突然这些功能不再受支持,那么这是您的事,而不是库作者的事。如果用户滥用你的代码,那是他的事,不是你的事。“仅按预期使用代码”。就我的两分钱。@GLES你的同事真的不值得信任吗?你不能指望他们不入侵数据库吗?@GLES:如果他们想入侵数据库,他们当然可以修改你的类的源代码?另外,
object.\uuuuu setattr\uuuuuuu(您的类实例'which\u key\u i\u like',value)
将破坏您尝试的任何操作。谢谢!我迫切需要这样一种技巧,建议使用一种神奇的方法。@GLES:请在使用此解决方案之前阅读。谢谢!我要试试这个。我忽略了“装饰者”这个主题:)现在我意识到它忽略了我:)