博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[ python ] 封装
阅读量:4340 次
发布时间:2019-06-07

本文共 4534 字,大约阅读时间需要 15 分钟。

类中的私有属性

在类中定义一个私有属性如下:

class Person(object):    def __init__(self, name):        self.__name = name    # 定义私有属性 self.__namep = Person('hkey')print(p.__name)    # 外部不能直接调用私有属性执行结果:Traceback (most recent call last):  File "E:/learn_python/day26/test6.py", line 11, in 
print(p.__name)AttributeError: 'Person' object has no attribute '__name'

 

 

私有属性的使用场景:

  1. 隐藏起一个属性,不想让类的外部调用
  2. 想要保护这个属性,不想让属性随便被改变
  3. 保护这个属性,不被子类继承

 

虽然私有属性不能直接从外部调用,但是我们可以通过对象.__dict__ 尝试来获取这个属性试试:

class Person(object):    def __init__(self, name):        self.__name = namep = Person('hkey')print(p.__dict__)print(p._Person__name)执行结果:{
'_Person__name': 'hkey'} # 执行 p.__dict__ 会直接获取对象的属性和方法hkey # 在外部可以通过 p._Person__name 来获取类中的私有属性

 

 

使用对象通过 _类名__属性名 来获取属性的方式并不推荐,在python中没有强制不允许查看类中私有属性,一切都靠自觉;

 

将类中的方法当作属性查看修改删除

 

 

property  将方法变成属性

一个实例: 写一个类,计算圆的周长和面积

from math import piclass Circle(object):    def __init__(self, r):        self.__r = r    def per(self):    # 圆的周长        return 2*pi*self.__r    def area(self):    # 圆的面积        return pi * self.__r **2c = Circle(5)print(c.area())print(c.per())

 

 

在上面的代码中,我们要计算圆的周长和面积,都是通过对象.方法名() 去获取的。当我们使用 property 可以通过 对象.属性名 的方式调用函数内的方法,如下:

from math import piclass Circle(object):    def __init__(self, r):        self.__r = r    @property    # 通过装饰器的形式,将类中方法调用的方式修改为函数调用的方式    def per(self):        return 2*pi*self.__r    @property    def area(self):        return pi * self.__r **2c = Circle(5)print(c.area)print(c.per)

 

 

属性可以重新赋值,但是当使用 property 转换为属性调用的方式后,是不能直接赋值的。

class Person(object):    def __init__(self, name):        self.__name = name    @property    # 使用 property 改变类中函数的调用方式    def name(self):        return self.__name + ' run.'p = Person('hkey')print(p.name)

 

 

setter

 

当我们要修改对象 p 的 name 属性时,就需要使用 setter

class Person(object):    def __init__(self, name):        self.__name = name    @property    def name(self):        return self.__name + ' run.'    @name.setter    # 使用 setter 装饰器    def name(self, new_name):        self.__name = new_namep = Person('hkey')print(p.name)p.name = 'xiaofei'    # 就可以实现从新赋值print(p.name)

 

 

当使用 setter 时, 我们要明确命名规则:

 

当使用 setter 时,我们不仅可以赋值,还可以做一些判断

class Person(object):    def __init__(self, name):        self.__name = name    @property    def name(self):        return self.__name + ' run.'    @name.setter    def name(self, new_name):        if new_name.isalpha():  # new_name 必须是有字母或汉字组成            self.__name = new_namep = Person('hkey')print(p.name)p.name = '123'  # 字符串是由数字组成,赋值失败print(p.name)

 

 

deleter

 

这个组合中最不常用的装饰器:

作用:当要删除类中某个属性的时候使用 deleter 具体使用如下

class Person(object):    def __init__(self, name):        self.__name = name    @property    def name(self):        return self.__name + ' run.'    @name.setter    def name(self, new_name):        if new_name.isalpha():  # new_name 必须是有字母或汉字组成            self.__name = new_name    @name.deleter    def name(self):        print('\033[31;1m我要删除类中【__name】属性了.\033[0m')        del self.__namep = Person('hkey')del p.name执行结果:我要删除类中【__name】属性了.

 

 

一个实例, 商品打折的例子。

class Goods(object):    dicount = 0.5    def __init__(self, name, price):        self.name = name        self.__price = price    @property    def price(self):        return self.__price * Goods.dicountapple = Goods('apple', 10)pear = Goods('pear', 5)print(apple.price)print(pear.price)

 

 

在上面的实例中,当要改变所有商品的折扣时,只需要修改 dicount, 所有商品的折扣都会改变了。

 

classmethod 类方法

 

当要使用类方法时,需要满足以下两点:

  1. 把一个方法变成一个类中的方法,这个方法就直接可以被类调用,不需要依托任何对象
  2. 当一个方法的操作只涉及静态属性的时候,就应该使用 classmethod来装饰这个方法

 

还是上面商品打折的例子:

dicount 是一个类属性,我们就可以通过定义一个类方法来修改这个属性

class Goods(object):    dicount = 0.5    def __init__(self, name, price):        self.name = name        self.__price = price    @property    def price(self):        return self.__price * Goods.dicount    @classmethod    # 定义一个类方法    def modify_discount(cls, new_discount):    # cls: 类名,普通形参        cls.dicount = new_discountapple = Goods('apple', 10)pear = Goods('pear', 5)Goods.modify_discount(0.2)  # 打 0.2 折    # 调用方式 类名.类方法(普通形参)print(apple.price)print(pear.price)执行结果:2.01.0

 

 

staticmethod 静态方法

 

在完全面向对象的程序中,如果一个函数即和对象没有关系,也和类没有关系。那么就用 staticmethod 将这个函数变成一个静态方法

比如在纯面向对象的编程中,编写一个用户登录的类:

class Login(object):    def __init__(self, user, pwd):        self.user = user        self.pwd = pwd    def login(self):        pass    @staticmethod    # 静态方法虽然是在类中,和类是完全无关的;    def get_user_pwd():        user = input('输入用户名:')        pwd = input('输入密码:')        Login(user, pwd)Login.get_user_pwd()    # 进行登录

 

 

使用类方法和静态方法要注意以下几点:

  1. 类方法和静态方法 都是类调用的
  2. 对象可以调用类方法和静态方法,但是一般建议使用类名去调用
  3. 类方法有一个默认参数 cls 代表这个类,静态方法 没有默认的参数 就像函数一样

 

转载于:https://www.cnblogs.com/hukey/p/9963474.html

你可能感兴趣的文章
Windows下MongoDB的安装与设置MongoDB服务
查看>>
Microsoft.Jet.OLEDB.4.0”提供程序不支持 ITransactionLocal 接口。本地事务不可用于当前提供程序...
查看>>
Django 之Form
查看>>
开发ProxyServer的时候如何在一台PC上调试
查看>>
C#用于对用户输入数据进行校验的类
查看>>
低速前碰开发
查看>>
python-9-IO编程
查看>>
【GoLang】转载:我为什么放弃Go语言,哈哈
查看>>
【MySQL】MySQL 如何实现 唯一随机数ID
查看>>
【Redis】Redis分布式集群几点说道
查看>>
HDU2819(KB10-E 二分图最大匹配)
查看>>
mysql主从复制、redis基础、持久化和主从复制
查看>>
文档工具GitBook使用
查看>>
两个链表的第一个公共节点
查看>>
知道这20个正则表达式,能让你少写1,000行代码
查看>>
MariaDB 主从同步与热备(14)
查看>>
推荐的 CSS 书写顺序
查看>>
NIO:与 Buffer 一起使用 Channel
查看>>
Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析
查看>>
MFC接收ShellExecute多个参数
查看>>