iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >python3--面向对象的三大特性:封装,property,classmethod,staticmethod
  • 771
分享到

python3--面向对象的三大特性:封装,property,classmethod,staticmethod

三大面向对象特性 2023-01-30 21:01:46 771人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

python中的封装隐藏对象的属性和实现细节,仅对外提供公共访问方式好处:1 将变化隔离2 便于使用3 提供复用性4 提高安全性封装原则1 将不需要对外提供的内容都隐藏起来2 把属性都隐藏,提供公共方法对其访问私有变量和私有方法在Pytho

python中的封装

隐藏对象的属性和实现细节,仅对外提供公共访问方式

好处:

1 将变化隔离

2 便于使用

3 提供复用性

4 提高安全

封装原则

1 将不需要对外提供的内容都隐藏起来

2 把属性都隐藏,提供公共方法对其访问


私有变量和私有方法

Python中用双下划开头的方式将属性隐藏来(设置成私有的)

函数和属性装到了一个非全局的命名空间--封装

私有变量,错误示例

class A:
    __N = 'aaa'  # 静态变量
print(A.__N)

执行报错

AttributeError: type object 'A' has no attribute '__N'

这个__N就是类A的私有属性


定义一个私有的名字:就是在私有的名字前面加两条下划线__N = 'aaa',所谓私有,就是不能在类的外面去引用它

class A:
    __N = 'aaa'  # 静态变量
    def func(self):
        print(A.__N)  # 在类的内部使用正常
print(A.__dict__)

blob.png

可以看到类属性多了一个'_A__N':'aaa'的属性,其实这个_A__N 就是__N,这是python解释器自动做的一个变形操作

类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式

例子

class A:
    __N = 0  # 类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
    def __init__(self):
        self.__X = 10  # 变形为self._A__X
    def __foo(self):  # 变形为_A__foo
        print('from A')
    def bar(self):
        self.__foo()  # 只有在类内部才可以通过__foo的形式访问到
print(A._A__N)  # 是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形
a = A()
print(a._A__X)  # 是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形
a.bar()

执行结果

0

10

from A


一个私有的名字,在存储的过程中仍然会出现在A.__dict__中,所以我们仍然可以调用到,

python对其的名字进行了修改:_类名__名字

只不过在类的外部调用:需要_类名__名字去使用

在类的内部可以正常的使用名字

在类里面,只要你的代码遇到__名字,就会被python解释器自动的转换成_类名__名字

虽然上面的方式可以访问到私有的,但是却不建议这么做,约定俗成


私有的属性

示例

class B:
    def __init__(self, name):
        self.__name = name
    def func(self):
        print('in func: {}'.fORMat(self.__name))  # 外部通过调用func来获取类的私有属性
b = B('Sam')
b.func()

执行结果

in func: Sam


私有的方法

示例

class C:
    def __wahaha(self):
        print('wahaha')
    def ADCa(self):  # 外部通过调用ADCa()方法,来执行类的私有方法__wahaha()
        self.__wahaha()
c = C()
c.ADCa()

执行结果

wahaha


在类中,静态属性,方法,对象属性都可以变成私有的,只需要在这些名字之前加上__


例3

class F:
    pass
F.__name = 'Sam'  # 误区,不是在创建私有属性
print(F.__name)
print(F.__dict__)

执行结果

blob.png

可以很明确的看到__name并没有发生变形,变形只在类的内部发生,在类的外面创建的双下划线的属性,并不是私有属性


面试题

1 下面代码执行的结果是什么?为什么?

class D:
    def __func(self):
        print('in func')

class E(D):
    def __init__(self):
        self.__func()

e = E()

解答:

class D:
    def __func(self):  # 在类的内部遇到__,python解释器会自动变形成_D__func
        print('in func')

class E(D):
    def __init__(self):
        self.__func()  
        # 在类的内部遇到__,python解释器会自动变形成_E__func
        # 实例化一个对象e,首先会找到E类中的__init__方法
        # 遇到了__,所以会去找self._E__func()方法,子类E中没有找到
        # 就去父类中找,而父类中的__func变形成_D__func,而执行的是_E__func,所以会报错

e = E()

结果报错

AttributeError: 'E' object has no attribute '_E__func'


2 下面代码执行的结果是什么?为什么?

class D:
    def __init__(self):
        self.__func()
    def __func(self):
        print('in D')

class E(D):
    def __func(self):
        print('in E')
e = E()


解答

class D:  # 第一步加载类D
    def __init__(self):  # 第二步加载__init__  #第七步,由于子类没有init方法,所以找父类的
        self.__func()    # 第八步执行self.__func(),也就是_D__func
    def __func(self):    # 第三步加载_D__func,双下划线变形   # 第九步,执行_D__func()
        print('in D')    # 第10步打印 'in D'

class E(D):  # 第四步加载类E
    def __func(self):  # 第五步加载_E__func,双下划线变形
        print('in E')
e = E()      # 第六步,实例化一个对象e ,

执行结果

in D


java中的对比

public  共有的   在类的内部可以使用,子类可以使用,外部可以使用     python类中所有的常规名字

protect 保护的   在类的内部可以使用,子类可以使用,外部不可以使用   python中没有

private 私有的   只能在类的内部使用,子类和外部都不可以使用         python中的__名字


私有的用法

当一个方法不想被子类继承的时候

有些熟悉或者方法不希望从外部被调用,只想提供给内部的方法使用

示例1

描述一个房子,单价,面积,长宽高

class Room:
    def __init__(self, name, price, length, width, height):  # 名字,价格,长,宽,高
        self.name = name
        self.price = price
        self.__length = length  # 私有属性长
        self.__width = width  # 私有属性宽
        self.__height = height  # 私有属性高

    def area(self):
        return self.__length * self.__width  

r = Room('张三', 240000, 11, 5, 2)
print('姓名:{},房子价格:{},面积:{}'.format(r.name, r.price, r.area()))

执行结果

姓名:张三,房子价格:240000,面积:55


示例2

用户输入账号名和密码,把密码转换为对应的ascii,最后打印出账号名和转换后的ascii值

class Person:
    def __init__(self, name, pwd):
        self.name = name
        self.__pwd = pwd
    def __showpwd(self):
        s = []
        for i in self.__pwd:
            s.append(str(ord(i)))
        s2 = ''.join(s)
        return s2

p = Person('zhangsan', '12345')
print('账号名为:{},加密后的密码为:{}'.format(p.name, p._Person__showpwd()))

执行结果

账号名为:zhangsan,加密后的密码为:4950515253


property方法

将一个方法伪装成一个属性

1 并不会让你的代码有什么逻辑上的提高

2 只是从调用者的角度上换了一种方式,使之看起来更合理


示例

人体BMI指数

体质指数(BMI)=体重(kg) / 身高**2(m)

写一个类,描述人体BMI指数

class Person:
    def __init__(self, name, weight, height):
        self.name = name
        self.__height = height
        self.__weight = weight

    def cal_BMI(self):
        return self.__weight / self.__height ** 2

    @property
    def bmi(self):
        return self.__weight / self.__height ** 2

P = Person('张三', 67, 1.71)
print(P.bmi)

执行结果

22.91303307000445


在一个类加载的过程中,会先加载这个类中的名字,包括被property装饰的

在实例化对象的时候,python解释器会先到类的空间里看看有没有这个被装饰的属性,如果有就不能在自己对象的空间中创建这个属性了

示例

计算圆形类的,面积,周长,将方法伪装成属性,方法中一般涉及的都是一些计算过程

from math import pi
class Circle:
    def __init__(self, r):
        self.r = r
    @property
    def area(self):
        return self.r ** 2 * pi
    
    @property
    def perimeter(self):
        return 2 * pi * self.r
c = Circle(10)
print(c.area)
print(c.perimeter)

执行结果

314.1592653589793

62.83185307179586


例2

class Person:
    def __init__(self, name):
        self.__name = name  # 定义一个私有名字__name

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

    def set_name(self, new_name):
        if type(new_name) is str:  # 判断name的数据类型是否为字符串
            self.__name = new_name  # 赋值
        else:
            print('你提供的姓名数据类型不合法')
p = Person('Sam')
print(p.name)
p.set_name('Tom')
print(p.name)

执行结果

Sam

Tom


@func.setter --> func 对伪装的属性进行赋值的时候调用这个方法,一般情况下用来修改

示例:对方法伪装成的属性进行修改

class Person:
    def __init__(self, n):
        self.__name = n  # 私有的属性

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

    @name.setter  # 使用setter,一定要和property装饰的方法名相同,且要创建同名方法修改
    def name(self, new_name):
        if type(new_name) is str:
            self.__name = new_name
        else:
            print('你提供的姓名数据类型不合法')

p = Person('sam')
print(p.name)
p.name = 'Jack'  # 注意,修改使用等号,前面是老的名字,后面是新的名字
print(p.name)

执行结果

sam

Jack


@func.deleter --> func 在执行del 对象.func的时候调用这个方法 一般情况下用来做删除 基本不用

示例

class Person:
    def __init__(self, n):
        self.__name = n

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

    @name.deleter  # 使用deleter也要确保和property装饰的方法同名,且要创建一个相同方法
    def name(self):
        del self.__name
p = Person('Sam')
print(p.name)
del p.name  # 删除名字
print(p.name)  # 打印报错,因为名字已经被删除了

执行结果

AttributeError: 'Person' object has no attribute '_Person__name'


将一些需要随着一部分属性的变化而变化的值的计算过程 从方法 伪装成属性

将私有的属性保护起来,让修改的部分增加一些约束,来提高程序的稳定性和数据的安全性

示例:有个商品:原价,折扣,当我要查看价格的时候,肯定只看折后的价格

class Goods:
    def __init__(self, name, origin_price, discount):
        self.name = name
        self.__price = origin_price
        self.__discount = discount

    @property
    def price(self):
        return self.__price * self.__discount

    @price.setter
    def price(self, new_price):
        if type(new_price) is int or type(new_price) is float:
            self.__price = new_price
apple = Goods('apple', 5, 0.8)
print(apple.price)  # 打折后的价格
apple.price = 10  # 苹果价格上涨
print(apple.price)

执行结果

4.0

8.0


@claSSMethod

类方法 可以直接被类调用 不需要默认传对象参数 只需要传一个类参数就可以了

示例

class Goods:
    __discount = 0.8
    def __init__(self, name, origin_price):
        self.name = name
        self.__price = origin_price

    @property
    def price(self):
        return self.__price * Goods.__discount

    @classmethod
    def change_discount(cls, new_discount):
        cls.__discount = new_discount


apple = Goods('apple', 5)
banana = Goods('banbana', 8)
print(apple.price)
print(banana.price)

# 折扣价格变了,不打折
# 不依赖对象的方法 就应该定义成类方法 类方法可以任意的操作类中的静态变量
Goods.change_discount(1)  # 更改全局静态变量
print(apple.price)
print(banana.price)

执行结果

4.0

6.4

5

8


@staticmethod

当一个方法要使用对象的属性时 就是用普通的方法

当一个方法要使用类中的静态属性时 就是用类方法

当一个方法要既不使用对象的属性也不使用类中的静态属性时,就可以使用staticmethod静态方法

示例

class Student:
    def __init__(self): pass

    @staticmethod
    def login():  # login就是一个类中的静态方法 静态方法没有默认参数 就当成普通的函数使用即可
        user = input('user:')
        if user == 'root':
            print('success')
        else:
            print('faild')
Student.login()

执行结果

user:root

success


--结束END--

本文标题: python3--面向对象的三大特性:封装,property,classmethod,staticmethod

本文链接: https://www.lsjlt.com/news/179051.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • python3--面向对象的三大特性:封装,property,classmethod,staticmethod
    python中的封装隐藏对象的属性和实现细节,仅对外提供公共访问方式好处:1 将变化隔离2 便于使用3 提供复用性4 提高安全性封装原则1 将不需要对外提供的内容都隐藏起来2 把属性都隐藏,提供公共方法对其访问私有变量和私有方法在pytho...
    99+
    2023-01-30
    三大 面向对象 特性
  • Python面向对象的三大特性封装、继承、多态
    Python是一门面向对象的语言。面向对象都有三大特性:封装、继承、多态。 下面分别来说说这三大特性: 1、封装 隐藏对象的属性和实现细节,仅对外提供公共访问方式。在python中用...
    99+
    2024-04-02
  • python面向对象的三大特性
    一、 封装 广义的封装 :类中的成员 狭义的封装 :私有成员 表象:__名字 实际:_类名__名字 要求:只能在类的内部使用,既不能在类的外部调用,也不能在子类中使用 对象的作用:存储一些值,以后方便自己使用 class F...
    99+
    2023-01-31
    三大 面向对象 特性
  • Java面向对象的三大特性
    本篇内容主要讲解“Java面向对象的三大特性”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java面向对象的三大特性”吧!Java面向对象三大特性面向对象简称 OO(Object Oriente...
    99+
    2023-06-02
  • 面向对象以及三大特性
      1.函数式编程和面向对象的对比     题目:开发一个消息提醒的功能(邮件/短信/微信) def email(em,text): """ 发送邮件 :return: """ print(...
    99+
    2023-01-30
    三大 面向对象 特性
  • Python面向对象三大特征 封装、继承、多态
    目录1、封装1.1 私有属性和私有方法2、继承2.1 方法的重写2.2 在子类方法中调用父类方法2.3 多继承2.4 新式类和经典类 3、多态1、封装 封装: 根据 职责 将 属性 ...
    99+
    2024-04-02
  • javascript面向对象三大特征之封装的示例分析
    这篇文章主要介绍了javascript面向对象三大特征之封装的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。具体如下:封装封装(En...
    99+
    2024-04-02
  • Python面向对象的三大特性是什么
    这篇“Python面向对象的三大特性是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python面向对象的三大特性是什么...
    99+
    2023-07-02
  • Python面向对象三大特性是什么
    今天小编给大家分享一下Python面向对象三大特性是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。问:说说Python面...
    99+
    2023-06-19
  • Java轻松掌握面向对象的三大特性封装与继承和多态
    目录1.封装1.介绍2.封装的理解和好处3.封装的实现步骤2.继承1.介绍2.继承的基本语法3.继承的使用细节3.super关键字1.基本介绍2.基本语法3.细节与好处4.super...
    99+
    2024-04-02
  • Java面向对象特性深入刨析封装
    目录1.认识封装2.控制访问权限-访问修饰符3.理解封装必须要知道-包3.1理解包的概念3.2 导入包中的类3.3 自定义包3.4 包的访问权限控制3.5 java中常见的包前面已经...
    99+
    2024-04-02
  • 怎么理解Java面向对象三大特性
    这篇文章主要讲解了“怎么理解Java面向对象三大特性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Java面向对象三大特性”吧!继承Java中的继承只能单继承,但是可以通过内部类继承...
    99+
    2023-06-02
  • Python 面向对象编程的三大特性之继承
    目录Python  面向对象编程的三大特性之继承一、继承1、继承的实际栗子2、继承的好处3、继承的使用场景4、继承有几种?5、Python 中继承的简单语法二、不使用继承、...
    99+
    2024-04-02
  • python 面向对象三大特征详解
    目录一、面向对象三大特征介绍1、封装(隐藏)2、继承3、多态二、继承1、语法格式2、类成员的继承和重写3、super()获得父类定义4、设计模式_工厂模式实现5、设计模式_单例模式实...
    99+
    2024-04-02
  • Java面向对象编程的三大特征
    目录1.封装1.1.封装概念1.2.封装的好处1.3.封装的实现步骤2.继承2.1.继承概念2.2.继承的好处2.3.子类对象实例化过程3.多态3.1.多态基本介绍3.2.多态的具体...
    99+
    2024-04-02
  • php中面向对象的三大特性分别是什么
    这篇“php中面向对象的三大特性分别是什么”文章,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要参考一下,对于“php中面向对象的三大特性分别是什么”,小编整理了以下知识点,请大家跟着小编的步伐一步一步的慢慢理解,接...
    99+
    2023-06-06
  • python面向对象编程及三大特性是什么
    今天小编给大家分享一下python面向对象编程及三大特性是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。面向过程编程:“...
    99+
    2023-06-27
  • python面向对象三大特征是什么
    小编给大家分享一下python面向对象三大特征是什么,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、面向对象三大特征介绍Python 是面向对象的语言,也支持面向对象编程的三大特性:继承、封装(隐藏)、多态。1、封装(隐...
    99+
    2023-06-25
  • Java面向对象的封装特征深度解析
    目录面向对象三大特征封装private关键字——实现类封装访问器方法和更改器方法包——类的集合导入包从人的角度理解包不加访问权限——实现包封装总结在上一篇文章中,我们了解了面向对象的...
    99+
    2024-04-02
  • Java面向对象有三大特征是什么
    这篇文章主要讲解了“Java面向对象有三大特征是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java面向对象有三大特征是什么”吧!面向对象有三大特征:封装性、继承性、多态性。l&nbs...
    99+
    2023-06-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作