属性类型
__xxx__
的属于特殊变量,特殊变量是可以直接在外部访问的,不是私有属性
定义
class Person(object):
def __init__(self, name, age, sex, money, faceValue, word):
self.name = name
self.age = age
self.sex = sex
# 不能再外部直接访问__money的原因是python解释器对外把__money属性变为_Person__money。所以任然可以使用_Person__money来直接访问,但是强烈建议不要这么来用,因为不同版本的python解释器可能会把__money改成不同的名字
self.__money = money
self._faceValue = faceValue
self.__word__ = word
使用
class Person(object):
def __init__(self, name, age, sex, money, faceValue, word):
self.name = name
self.age = age
self.sex = sex
self.__money = money
self._faceValue = faceValue
self.__word__ = word
#定义公有方法间接访问私有属性
def getMoney(self):
return self.__money
def setMoney(self, value):
self.__money = value
def getFaceValue(self):
return self._faceValue
def setFaceValue(self, value):
self._faceValue = value
def play(self):
print("---------play")
self.__run()
#私有方法,只能在类的内部调用
def __run(self):
print("----------run")
per = Person(<span class="hljs-string">"liudh"</span>, <span class="hljs-number">55</span>, <span class="hljs-string">"男"</span>, <span class="hljs-number">100</span>, <span class="hljs-number">99</span>, <span class="hljs-string">"good"</span>)
<span class="hljs-comment"># 在类的外部访问对象属性</span>
print(per.name)
<span class="hljs-comment"># 无法在类的外部直接访问私有属性</span>
<span class="hljs-comment"># print(per.__money)</span>
<span class="hljs-comment"># 通过调用公有方法间接访问私有属性</span>
print(per.getMoney())
per.setMoney(<span class="hljs-number">10</span>)
print(per.getMoney())
<span class="hljs-comment"># print(per._Person__money) #以后不要这么使用</span>
<span class="hljs-comment"># 无法在类的外部直接调用私有方法</span>
<span class="hljs-comment"># per.__run()</span>
per.play()
<span class="hljs-comment"># print(per._faceValue) # 不要这么用</span>
print(per.getFaceValue())
print(per.__word__)
目的
让访问私有属性像访问公有属性那样方便,让私有属性可以使用点语法
访问私有属性的原始方式:使用公有方法访问私有属性
class Person(object):
def __init__(self, name, age, sex, money):
self.name = name
self.age = age
self.sex = sex
self.__money = money
def getMoney(self):
return self.__money
def setMoney(self, value):
self.__money = value
通过访问公有方法间接访问私有属性
print(per.getMoney())
per.setMoney(1000)
print(per.getMoney())
想让访问私有属性的方式类似访问普通属性
使用@property让私有属性可以使用点语法。但本质上还是调用公有方法访问的私有属性,只不过看起来比较美丽
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span><span class="hljs-params">(object)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, name, age, sex, money)</span>:</span>
self.name = name
self.age = age
self.sex = sex
self.__money = money
<span class="hljs-comment"># 取值,当 对象.money 时相当于访问了该方法</span>
<span class="hljs-comment"># 函数名为私有属性去掉下划线的部分</span>
<span class="hljs-meta"> @property</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">money</span><span class="hljs-params">(self)</span>:</span>
<span class="hljs-keyword">return</span> self.__money
<span class="hljs-comment"># 赋值,当 对象.money = 值 时相当于调用该方法,“值”当做参数传递进来(value = "值")</span>
<span class="hljs-meta"> @money.setter</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">money</span><span class="hljs-params">(self, value)</span>:</span>
self.__money = value
per = Person(<span class="hljs-string">"liudh"</span>, <span class="hljs-number">55</span>, <span class="hljs-string">"男"</span>, <span class="hljs-number">100</span>)
<span class="hljs-comment"># 访问私有属性的方式类似访问普通属性</span>
print(per.money)
per.money = <span class="hljs-number">200</span>
print(per.money)
准备代码
class Person(object):
def __init__(self, name):
self.name = name
def say(self):
print("%s is a good man"%(self.name))
per1 = Person("liudh")
per2 = Person("daolang")
per1.say()
per2.say()
增加对象属性
# 增加对象属性(实例化一个对象后,可以给对象绑定任意的属性和方法)
per1.age = 55 #如果属性不存在则变为增加属性
print(per1.age) #给对象增加对象属性,只会给当前对象增加
# print(per2.age) #per2没有age属性
增加类属性
# 每个对象同时增加
Person.city = "北京"
print(per1.city)
print(per2.city)
增加对象方法
增加的既不是对象方法也不是类方法,有点类似静态方法
# def run():
# print("--------run")
# per1.run = run
# per1.run()
增加的确实是对象方法,但是需要手动给形参self传递参数
# def run(self):
# print("------------run")
# self.say()
# per1.run = run
# per1.run(per1)
合适的方式
def run(self):
print("------------run")
self.say()
from types import MethodType
per1.run = MethodType(run, per1)
per1.run()
添加类方法
def play(cls):
print("-----play")
from types import MethodType
Person.play = MethodType(play, Person)
Person.play()
思考
想要限制实例的属性,不让对象随意添加属性,只能添加一些我们规定
解决
在定义类时,定义一个__slots__
特殊属性,限制该类实例能添加的属性
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span><span class="hljs-params">(object)</span>:</span>
__slots__ = (<span class="hljs-string">"name"</span>, <span class="hljs-string">"age"</span>, <span class="hljs-string">"sex"</span>, <span class="hljs-string">"money"</span>)
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, name)</span>:</span>
self.name = name
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">say</span><span class="hljs-params">(self)</span>:</span>
print(<span class="hljs-string">"%s is a good man"</span>%(self.name))
使用
per = Person("liudh")
per.age = 55
per.sex = "男"
# per.faceValue = 100
# Person.city = "北京"