当在类体内定义好各种属性后,外部是可以随便添加属性的,Python中类如何限制实例的属性?

Python自带了很多定制类,诸如__slots__,__str__

__slots__

__slots__方法是在类创建时,为实例限定属性的

class Student(object):
__slots__=('name','age')
pass >>>s = Student()
>>>s.name='tom'
>>>s.age='age'
>>>s.score= #AttributeError: 'Student' object has no attribute 'score'

当__slots__已经进行限定时,再去给实例绑定没有限定的属性,就会报错。

__slots__作用域仅限当前的类,当父类中有__slots__属性时,子类中并没有限制,当子类中定义__slots__时,子类的实例限制就是子类本身加上父类的__slots__。

__str__和__repr__

如果要把一个类的实例变成 str,就需要实现特殊方法__str__():

class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __str__(self):
return '(Person: %s, %s)' % (self.name, self.gender) >>>p = Person('tom','male')
>>>print(p)
(Person:tom,male)
>>>p #直接打印p __str__不会被调用
<main.Person object at 0x10c941890>

因为 Python 定义了__str__()__repr__()两种方法,__str__()用于显示给用户,而__repr__()用于显示给开发人员:

这个函数,对应repr(object)这个功能。意思是当需要显示一个对象在屏幕上时,将这个对象的属性或者是方法整理成一个可以打印输出的格式。

这个功能与eval也可以对应。打印出的结果直接放到eval里,通常可以获得原来的对象。

>>> from datetime import datetime
>>> t1 = datetime.now()
>>> t1
datetime.datetime(2017, 12, 8, 16, 50, 47, 766613)
>>> print(t1)
2017-12-08 16:50:47.766613
>>> print(repr(t1))
datetime.datetime(2017, 12, 8, 16, 50, 47, 766613)
>>> print(str(t1))
2017-12-08 16:50:47.766613

与此相类似的功能是__str__

比如你有一个People类,当打印时你只希望它打印出人名,那么你可以在__str__函数里写上return self.name , 这样当需要People当作一个字符串时,返回的就是人名。

有一个偷懒的定义__repr__的方法:

class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __str__(self):
return '(Person: %s, %s)' % (self.name, self.gender)
__repr__ = __str__

__len__

如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。

要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。

例如,我们写一个 Students 类,把名字传进去:

class Students(object):
def __init__(self, *args):
self.names = args
def __len__(self):
return len(self.names) >>>s = Student('a','b','c') #只要正确实现了__len__()方法,就可以用len()函数返回Students实例的“长度”
>>>print len(s)
3

__call__

Python所有的函数都是可调用对象。

一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()

我们把 Person 类变成一个可调用对象:

class Person(object):
def __init__(self, name, sex):
self.name = name
self.sex = sex def __call__(self, friend):
print('My name is %s...' % self.name)
print('My friend is %s...' % friend) >>>p = Person('tom','boy')
>>>p('jerry') #对实例直接调用
My name is tom
My friend is jerry

枚举

定义枚举引入模块enum,枚举类继承的时Enum类

from enum import Enum

class Book(Enum):
a = 1
math = 2
english = 3
linux = 4
c++ = 5

访问枚举有很多方法

>>>Book.a
<Book.a: 1> >>>Book(1)
<Book.a: 1> >>>print(Book.a)
Book.a >>>print(Book(1))
Book.a >>>Book.a.name
'a' >>>Book.a.value
1

如果枚举中成员名有重复的话,就会报错TypeError: Attempted to reuse key: 'a'

成员的值时允许重复的,但是访问时还是第一个成员属性,Python将重复的第二个成员看做第一个的别名

from enum import Enum

class Book(Enum):
a = 1
b = 1 >>>Book.a
<Book.a: 1> >>>Book.b #访问b也变成了打印a属性,b被视为a的别名
<Book.a :1>

如果限制枚举没有重复的话,引入unique模块,unique是一个类装饰器,用来约束值

from enum import Enum,unique

@unique
class Book(Enum):
a = 1
b = 1 >>>print(Book.a.value)
ValueError:dupplicate values found in <enum 'Book'>:b -> a

枚举支持迭代器

>>>for b in Book:
print(b) Book.a、...

成员值重复时,只能拿到第一个成员,若要不管重复,列出所有的,使用__members__方法

from enum import Enum

class Book(Enum):
a = 1
math = 2
english = 3
linux = 4
c++ = 5 for b in Book.__members__.items():
print(b)
#以元组形式打印
('a',<Book.a: 1>)、('math',<Book.math: 2>)、、、

Python面向对象高级编程-__slots__、定制类,枚举的更多相关文章

  1. python 面向对象高级编程

    数据封装.继承和多态只是面向对象程序设计中最基础的3个概念.在Python中,面向对象还有很多高级特性,允许我们写出非常强大的功能. 我们会讨论多重继承.定制类.元类等概念.

  2. python面向对象高级编程

    正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性.先定义class: >>> class Studen ...

  3. 【Python学习之七】面向对象高级编程——__slots__的使用

    1.Python中的属性和方法的绑定 正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法. (1)首先,定义一个class:  class Stu ...

  4. python面向对象高级:__slots__

    __slots__ 一个在有着数以千计的对象的类的时候节省内存的方法. 在Python中,每个类都有实例属性.默认情况下Python用一个字典来保存一个对象的实例属性.这非常有用,因为它允许我们在运行 ...

  5. Python面向对象高级编程:__slot__(给实例添加方法、属性)

    纲要: 本章总的来说是给实例添加属性,给类添加方法两个主题,以及相应的作用范围.总结如下: 1.给实例添加属性(作用范围:当然是只对当前实例有效): 2.用__slots__限制可以给实例添加的属性( ...

  6. Python面向对象高级编程:@property--把方法变为属性

    为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数: >>> ...

  7. Python面向对象高级编程-@property

    使用@property 在绑定属性时,如果直接把属性暴露出去,虽然写起来简单,但是没法检查参数,导致可以把成绩随便改: >>> class Student(object): pass ...

  8. Python面向对象高级编程-_slots_

    使用_slots_ 正常情况下,当定义一个class,创建一个class的实例后,可以给实例绑定任何属性和方法,这就是动态语言的灵活性.先定义class: >>> class Stu ...

  9. Python:面向对象编程3 定制类(有更新)

    Python:面向对象编程3  定制类(有更新) ⚠️本文主要内容为对Data model相关知识点的提取学习记录.(内容来自文档和部分网页教程案例) ⚠️:这个连接指向<流畅的python&g ...

随机推荐

  1. Anaconda 安装后配置环境变量

    Anaconda 安装后在 cmd 中运算 python 无效, 是环境变量没有生效.正常安装需要有三个,配置好就行. D:\xwapp\ProgramData\Anaconda3 D:\xwapp\ ...

  2. ArrayList.clear、=null、new Arraylist之间的对比区别

    参考博文 1.使用ArrayList的对象方法clear() List list = new ArrayList(); List list1 = list; list.add(1); list.add ...

  3. 草珊瑚理解IFC(inline formatting context)

    1. 认识字体font-family 字体渲染的实际高度, 由字体本身的设置(升部ascender,降部descender,大写字母高度Capital Height,小写字母高度X-Height等等) ...

  4. jqGrid API (转)

    来源:https://www.cnblogs.com/MonaSong/p/5109991.html JQGrid是一个在jquery基础上做的一个表格控件,以ajax的方式和服务器端通信. JQGr ...

  5. c#四舍五入取整

    Math.Round(3.45, 0, MidpointRounding.AwayFromZero) 上取整或下取整 Math.Ceiling(3.1)=4; Math.Floor(3.9)=3;

  6. file_put_contents结合print_r,打造日志功能

    <?php $log = []; $log['name'] = '张三'; $log['age'] = '15'; $log['date'] = date('Y-m-d'); echo prin ...

  7. Eclipse使用之将Git项目转为Maven项目, ( 注意: 最后没有pom.xml文件的, 要转化下 )

    Eclipse使用之将Git项目转为Maven项目(全图解) 2017年08月11日 09:24:31 阅读数:427 1.打开Eclipse,File->Import 2.Git->Pr ...

  8. PowerDesign的简单使用方法

    PowerDesigner是一款功能非常强大的建模工具软件,足以与Rose比肩,同样是当今最著名的建模软件之一.Rose是专攻UML对象模型的建模工具,之后才向数据库建模发展,而PowerDesign ...

  9. leecode第五题(最长回文子串)

    class Solution { public: string longestPalindrome(string s) { int len = s.length(); || len == ) retu ...

  10. 《剑指offer》第五十五题(平衡二叉树)

    // 面试题55(二):平衡二叉树 // 题目:输入一棵二叉树的根结点,判断该树是不是平衡二叉树.如果某二叉树中 // 任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树. #includ ...