前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面向对象-访问限制

面向对象-访问限制

作者头像
星哥玩云
发布2022-09-08 13:15:42
1.1K0
发布2022-09-08 13:15:42
举报
文章被收录于专栏:开源部署

一、限制访问

属性类型

  • 公有 在内部和外部均可访问 目前为止,正常定义在构造函数中
  • 私有
    • 如果要让内部属性不被外部访问,可以把属性名称前加上两个下滑线
    • python中实例的变量以__开头,就变成了一个私有属性(private),只能在类的内部访问,无法在类的外部直接访问
    • 属性前加一个下划线,这样的属性约定俗成的表示请把我看成私有的属性来用(虽然可以在类的外部直接访问),不要在外部直接访问
  • 特殊 在python中,变量名类似__xxx__的属于特殊变量,特殊变量是可以直接在外部访问的,不是私有属性

定义

代码语言:javascript
复制
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

使用

代码语言:javascript
复制
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")
代码语言:javascript
复制
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__)

二、@property

目的

让访问私有属性像访问公有属性那样方便,让私有属性可以使用点语法

访问私有属性的原始方式:使用公有方法访问私有属性

代码语言:javascript
复制
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让私有属性可以使用点语法。但本质上还是调用公有方法访问的私有属性,只不过看起来比较美丽

代码语言:javascript
复制
<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)

三、动态给实例对象添加属性与方法

准备代码

代码语言:javascript
复制
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()

增加对象属性

代码语言:javascript
复制
# 增加对象属性(实例化一个对象后,可以给对象绑定任意的属性和方法)
per1.age = 55 #如果属性不存在则变为增加属性
print(per1.age) #给对象增加对象属性,只会给当前对象增加
# print(per2.age) #per2没有age属性

增加类属性

代码语言:javascript
复制
# 每个对象同时增加
Person.city = "北京"
print(per1.city)
print(per2.city)

增加对象方法

增加的既不是对象方法也不是类方法,有点类似静态方法

代码语言:javascript
复制
# def run():
#     print("--------run")
# per1.run = run
# per1.run()

增加的确实是对象方法,但是需要手动给形参self传递参数

代码语言:javascript
复制
# def run(self):
#     print("------------run")
#     self.say()
# per1.run = run
# per1.run(per1)

合适的方式

代码语言:javascript
复制
def run(self):
    print("------------run")
    self.say()
from types import MethodType
per1.run = MethodType(run, per1)
per1.run()

添加类方法

代码语言:javascript
复制
def play(cls):
    print("-----play")
from types import MethodType
Person.play = MethodType(play, Person)
Person.play()

四、使用__slots__属性限制增加

思考

想要限制实例的属性,不让对象随意添加属性,只能添加一些我们规定

解决

在定义类时,定义一个__slots__特殊属性,限制该类实例能添加的属性

代码语言:javascript
复制
<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))

使用

代码语言:javascript
复制
per = Person("liudh")
per.age = 55
per.sex = "男"
# per.faceValue = 100
# Person.city = "北京"
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、限制访问
  • 二、@property
  • 三、动态给实例对象添加属性与方法
  • 四、使用__slots__属性限制增加
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档