泉水青年之家 發表於 2019-6-19 16:04:00

python面向对象之封装

<h2 id="1-封装实际封装python中的封装只是一个约定">1. 封装(实际封装python中的封装只是一个约定)</h2>
<h3 id="第一层面的封装类就好像一个袋子这就是一种封装">第一层面的封装:类就好像一个袋子,这就是一种封装</h3>
<p><strong>第一阶段:</strong></p>
<pre><code class="language-python"># 如果我们要定义学生jack如何定义?
name = 'jack'
age = 17
sex = '男'
</code></pre>
<pre><code class="language-txt">这三个变量可以用来形容jack这个人(当然你也可以使用字典,列表去描述).但是我们用三个变量去形容这个人,有什么弊端?
        弊端:太零散,如果学生太多,需要有很多变量去描述
为了解决这个问题,因此才有了类。
</code></pre>
<p><strong>第二阶段:</strong></p>
<pre><code class="language-python">class Student(object):

    def __init__(self,name,age,sex):
      self.name = name
      self.age = age
      self.sex = sex

one = Student('jack',17,'男') # 这里的one就相当于一个学生jack,所有的属性都封装到了one变量中。这里的Student类,相当于一个模板。只要给定它name,age,sex,它就能创建出一个学生对象。
two = Student('aaa',16,'男')
three = Student('bbb',15,'女')
four = Student('ccc',14,'男')
five = Student('ddd',13,'女')
print(f'姓名:{one.name}   年龄:{one.age}    性别:{one.sex}')
</code></pre>
<pre><code class="language-txt">姓名:jack   年龄:17    性别:男
</code></pre>
<p>到这里,不知道你是否已经体会到使用类封装的便利没!</p>
<h3 id="第二层面的封装类中定义私有的只有类内部使用外部无法访问比如_杠--__杠杠-">第二层面的封装:类中定义私有的,只有类内部使用,外部无法访问(比如_(杠)__(杠杠) )</h3>
<p><strong>第一阶段:</strong></p>
<pre><code class="language-python">class Student(object):

    def __init__(self,name,age,sex):
      self.name = name
      self.age = age
      self.sex = sex


one = Student('plf',18,'男')
one.name = 'who'
one.age = -28
one.sex = '人妖'
print(f'姓名:{one.name}   年龄:{one.age}    性别:{one.sex}')
</code></pre>
<pre><code class="language-txt">姓名:who   年龄:-28    性别:人妖
</code></pre>
<p><mark>问题:</mark>我们在外部能随意访问到对象one的属性,并且随意修改,这样数据是不安全的,因为我们需要将属性隐藏起来。那我们应该如何去做了?</p>
<p><strong>第二阶段:</strong></p>
<pre><code class="language-python">class Student(object):

    def __init__(self,name,age,sex):
      self.__name = name
      self.__age = age
      self.__sex = sex

one = Student('plf',18,'男')

print(one._Student__name)
print(one._Student__age)
print(one._Student__sex)

one._Student__age = 20       
print(one._Student__age)


rint(one.__name)       # 报错,无该属性
print(one.name)         # 报错,无该属性
</code></pre>
<pre><code class="language-txt">plf
18

20
</code></pre>
<p>此时发现,我们虽然不能使用one.name或者one.__name访问到该属性。但是我们可使用one._Student__age访问到对象的age属性并且能修改。说明python在设置私有属性的时候,只是把属性的名字换成了其他的名字。</p>
<p><mark>总结:</mark></p>
<p>​                类中以_或者__的属性,都是私有属性,禁止外部调用。虽然我们可以通过特殊的手段获取到,并且赋值,但是最好不要这么做(约定俗成)</p>
<p><mark>问题:</mark>现在我将name,age,sex设置为私有属性,但是我又想让他们通过我指定的接口去访问或者修改我的属性,应该如何实现了?</p>
<p><strong>第三阶段:</strong></p>
<pre><code class="language-python">Student(object):

    def __init__(self,name,age,sex):
      self.__name = name
      self.__age = age
      self.__sex = sex

    def get_name(self):
      return self.__name


    def set_name(self,name):
      if len(name) &gt; 1 :
            self.__name = name
      else:
            print("name的长度必须要大于1个长度")

    def get_age(self):
      return self.__age

    def set_age(self, age):
      if age &gt; 0 and age &lt; 150:
            self.__age = age
      else:
            print("输入的年龄必须要大于0,小于150岁")

one = Student('plf',18,'男')

one.set_name('a')       # 通过自己设置接口,可以有效规避脏数据
print(one.get_name())       # 通过接口获取数据


one.set_age(-9)         # 通过自己设置接口,可以有效规避脏数据
print(one.get_age())    # 通过接口获取数据
</code></pre>
<pre><code class="language-txt">name的长度必须要大于1个长度
plf
输入的年龄必须要大于0,小于150岁
18
</code></pre>
<p>这样我们就自定义了自己属性的接口,它的好处在于:规避脏数据</p>
<p>问题:使用接口设置获取数据 和 使用点方法(one.name = 18 或者print(one.name))设置数据相比, 点方法使用更方便,我们有什么方法达到既能使用点方法,同时又能让点方法直接调用到我们的接口了? 其他python已经帮我们实现了,让我们一起看一下吧!</p>
<p><strong>第四阶段:</strong></p>
<pre><code class="language-python">class Student(object):

    def __init__(self,name,age,sex):
      self.__name = name
      self.__age = age
      self.__sex = sex

    @property
    def name(self):
      return self.__name

    @name.setter
    def name(self,name):
      if len(name) &gt; 1 :
            self.__name = name
      else:
            print("name的长度必须要大于1个长度")

    @property
    def age(self):
      return self.__age

    @age.setter
    def age(self, age):
      if age &gt; 0 and age &lt; 150:
            self.__age = age
      else:
            print("输入的年龄必须要大于0,小于150岁")


one = Student('plf',18,'男')

one.name = '张三'
print(one.name)

one.age = 170
print(one.age)
</code></pre>
<pre><code class="language-txt">张三
输入的年龄必须要大于0,小于150岁
18
</code></pre>
<p>总结:</p>
<ol>
<li>使用 @property 装饰器时,接口名不必与属性名相同.</li>
<li>凡是赋值语句,就会触发set方法。获取属性值,会触发get方法</li>
</ol><br><br>
来源:https://www.cnblogs.com/plf-Jack/p/11051933.html
頁: [1]
查看完整版本: python面向对象之封装