__slots__

@property

多重继承

定制类

枚举类

元类

【使用__slots__】

1、动态语言的一个特点就是允许给实例绑定任意的方法和变量,而静态语言(例如Java)必须事先将属性方法写进类里。

给实例绑定变量:

>>> class Student:
... pass
...
>>> s = Student()
>>> s.name = 'Lily'
>>> s.name
'Lily'

给实例绑定方法需要借助types模块的MethodType方法:

>>> def setAge(self, age):
... self.age = age
...
>>> from types import MethodType
>>> s.setAge = MethodType(setAge, s)
>>> s.setAge(5)
>>> s.age
5

还可以给class绑定方法,使得方法对所有实例都有效:

>>> Student.setAge = setAge

2、万一需要限制属性怎么办?即只允许类的实例添加有限个属性。

这个时候可以使用一个特殊的类变量__slots__:

>>> class Employee(object):
... __slots__ = ('name', 'salary')
...
>>> e = Employee()
>>> e.name = 'Wang fang'
>>> e.salary = 18000
>>> e.age = 18 # age无法被添加为实例的属性!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Employee' object has no attribute 'age'

但是需要注意的是,__slots__对继承的子类是不起作用的!

【使用@property】

1、简而言之,@property就是一个类的方法的“装饰器”,添加在类的方法名的上一行,作用是把一个方法变成属性调用(即允许s.field这种访问方式),又能进行适当的参数检查。一个简单的例子:

#!/usr/bin/env python3
# -*- coding: utf-8 -*- class Movie(object): # 把一个getter方法变成属性
@property
def title(self):
return self._title # 不能和装饰器@title.setter重名,所以使用_title @title.setter
def title(self, title):
if not isinstance(title, str):
raise ValueError('title must be a str!')
self._title = title # 类测试
if __name__ == '__main__':
m = Movie()
# m.title = 123
m.title = 'Tokyo Ghoul'
print(m.title)

如果输入的title不是str类型,则会输出:

Traceback (most recent call last):
File "D:\labs\test.py", line 20, in <module>
File "D:\labs\test.py", line 14, in title
ValueError: title must be a str!

2、如果要将上面的title属性改为只读,只需要删去setter方法就可以了。

3、练习。

#!/usr/bin/env python3
# -*- coding: utf-8 -*- class Screen(object): @property
def width(self):
return self._width @width.setter
def width(self, width):
if width <= 0:
raise ValueError('width must larger than 0')
self._width = width @property
def height(self):
return self._height @height.setter
def height(self, height):
if height <= 0:
raise ValueError('height must larger than 0')
self._height = height @property
def area(self):
return self._width * self._height

测试结果:

>>> from test import Screen
>>> s = Screen()
>>> s.width = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\labs\test.py", line 13, in width
raise ValueError('width must larger than 0')
ValueError: width must larger than 0
>>> s.width = 80
>>> s.height = 70
>>> s.area = 10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> s.area
5600

【多重继承】

1、多重继承:类似于Java可以实现多个接口。(仅仅是类似,不等于!)

2、引用网友:第一个继承的是生父,后边的都是继父,继父的名字后面要加MixIn表明身份,如果方法有冲突,优先继承生父的。

class Dog(Mammal, RunnableMixIn, CarnivorousMixIn):
pass

注:第一个是主线继承,后两个是增加的功能。

【定制类】

1、__str__()、__repr__()类似于Java中的toString()。前者用于s.print(object)、后者用于直接输入s时的输出。

def __str__(self):
... return 'Student object (name: %s)' % self.name

偷懒的写法:写完__str__()后,__repr__ = __str__

2、__iter__()、__next__()。简单的例子:

#!/usr/bin/env python3
# -*- coding: utf- -*- class f():
def __init__(self):
self.a = def __iter__(self):
return self # 返回一个迭代对象给for def __next__(self): # 实现一个next方法给for调用
self.a +=
return self.a

4、__getitem__:让自定义对象表现得像list、str等类型一样。(可以进行索引、切片等操作)

class f():
def __getitem__(self, n):
return n
>>> from test import f
>>> f()[1]
1
>>> f()[3]
3

如果要支持切片:

class f():
def __getitem__(self, n):
if isinstance(n, int):
return n
if isinstance(n, slice):
start = n.start
stop = n.stop
if start == None: #例如[:3]默认为[0:3]
start = 0
L = []
for x in range(start, stop):
L.append(x)
return L
>>> f()[1:3]
[1, 2]

5、__getattr__:attr是attribute的简写。当实例本身不具备某个属性,却又强行被调用的时候会调用该函数。

class f():
def __init__(self):
self.a = 1111
self.b = 33333 def __getattr__(self, attr):
return "i had not attribute " + attr + "!"
>>> f().a
1111
>>> f().b
33333
>>> f().c
'i had not attribute c!'

当然也可以返回函数。

利用完全动态的__getattr__,可以写出一个链式调用。。。

6、__call__。

1)判断一个变量是对象还是函数:callable()。

2)把对象变成函数的方法:重写__call__方法。

such:

class f:
def __call__(self, a, b):
return a + b
>>> sum = f()
>>> sum(1, 2)
3

更多python的定制方法参考python官方文档。

【使用枚举类】

在Python中枚举类型也可以被视为一个类。

1、有两种方式可以创建这种类。

1)赋值法。

>>> from enum import Enum
>>> Colors = Enum('Colors', ('RED', 'YELLOW', 'BLUE'))

自然的操作,尝试打印一个Enum常量:

>>> Colors.RED
<Colors.RED: 1>

2)继承Enum。

from enum import Enum, unique

@unique
class Colors(Enum):
RED = 10086
YELLOW = 111
BLUE = 2222

尝试打印:

>>> from test import Colors
>>> Colors.RED
<Colors.RED: 10086>

10086即是RED的value。ps:@unique装饰器可以帮助检查有没有重复值。

2、枚举类用于逻辑关系运算 & 打印枚举类型变量

>>> myColor = Colors.BLUE
>>> myColor == Colors.RED
False
>>> print(myColor)
Colors.BLUE

【使用元类】

1、Python中的type()。

type()是用来干嘛的呢?根据字面上的意思很容易想到,可以通过type来输出Python中各种构件的类型,例如:

>>> type(1)
<class 'int'>
>>> type('hi python')
<class 'str'>
>>> type(lambda x: x)
<class 'function'>

尝试传入类名、对象会发现:

>>> class MyClass(object):
... pass
...
>>> type(MyClass)
<class 'type'>
>>> type(MyClass())
<class '__main__.MyClass'>

MyClass()对象的类型是MyClass,而MyClass类的类型是type!

这就说明,MyClass本身也可以被看作是由type创建的对象,而MyClass这个对象又具备创建对象的能力。

因此,type()除了可以用于查看各种Python构件的类型外,还可以用来创建类。

实际上在Python的解释器内部创建类的工作都是自动调用type()完成的。那么如何手动调用type()呢?

只需要将传统的class创建方式映射到type()上来就可以了。

一个传统的dog:

class Dog(object):

    def __init__(self, name, age):
self.name = name
self.age = age def run(self):
print(self.name + ' run!\n')
>>> from test import Dog
>>> i = Dog('Huahua', 2)
>>> i.run()
Huahua run!

一个type()创建的dog类:

# 先把组件写好

# 构造器
def f1(self, name, age):
self.name = name
self.age = age # run方法
def f2(self):
print(self.name + ' run!\n') # 组装成type()
Dog = type('Dog', (object,), dict(__init__=f1, run=f2))

测试:

>>> def f1(self, name, age):
... self.name = name
... self.age = age
...
>>> def f2(self):
... print(self.name + ' run!\n')
...
>>> Dog = type('Dog', (object,), dict(__init__=f1, run=f2))
>>> i = Dog('Lele', 3)
>>> i.run()
Lele run!

为什么使用type()而不是class来创建类呢?因为type()更具动态性。

2、元类。参考博客:深刻理解Python中的元类

为什么使用metaclass?和使用type一样,为了创建基于上下文的类。

什么是metaclass?type就是Python内置的一个metaclass!

一个使用metaclass会让事情变得简单的例子:数据库的GUI。(用type做不了,非metaclass不可)

定义metaclass

用metaclass创建类

这里是FO是

【Python】__slots__ 、@property、多重继承、定制类、枚举类、元类的更多相关文章

  1. [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...

  2. python-元类和使用元类实现简单的ORM

    元类 面向对象中,对象是类的实例,即对象是通过类创建出来的,在python中,一切皆对象,同样,类也是一个对象,叫做类对象,只是这个类对象拥有创建其子对象(实例对象)的能力.既然类是对象,那么类是通过 ...

  3. Python说文解字_详解元类

    1.深入理解一切接对象: 1.1 什么是类和对象? 首先明白元类之前要明白什么叫做类.类是面向对象object oriented programming的重要概念.在面向对象中类和对象是最基本的两个概 ...

  4. Python内置类属性,元类研究

    Python内置类属性 我觉得一切都是对象,对象和元类对象,类对象其实都是一样的,我在最后进行了证明,但是只能证明一半,最后由于元类的父类是type,他可以阻挡对object属性的访问,告终 __di ...

  5. 深刻理解Python中的元类(metaclass)以及元类实现单例模式

    在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍 ...

  6. Python元类(metaclass)以及元类实现单例模式

    这里将一篇写的非常好的文章基本照搬过来吧,这是一篇在Stack overflow上很热的帖子,我看http://blog.jobbole.com/21351/这篇博客对其进行了翻译. 一.理解类也是对 ...

  7. Python 爬取各大代理IP网站(元类封装)

    import requests from pyquery import PyQuery as pq base_headers = { 'User-Agent': 'Mozilla/5.0 (Windo ...

  8. 元类理解与元类编程 《Python3网络爬虫开发》中第九章代理的使用代码Crawler中代码的理解

    __new__与__init__的理解 __new__()方法是在创建实例之前被调用的,它的作用是创建一个实例,然后返回该实例对象,它是一个静态方法. __init__() 当实例被创建完成之后被调用 ...

  9. Python面向对象 -- slots, @property、多重继承MixIn、定制类(str, iter, getitem, getattr, call, callable函数,可调用对象)、元类(type, metaclass)

    面向对象设计中最基础的3个概念:数据封装.继承和多态 动态给class增加功能 正常情况下,当定义了一个class,然后创建了一个class的实例后,可以在程序运行的过程中给该实例绑定任何属性和方法, ...

随机推荐

  1. matlab 中关于 varargin 参数

    varargin 提供了一种函数可变参数列表机制,允许调用者调用该函数时根据需要来改变输入参数的个数: varargin{1}代表可变参数列表的第一个实参,同理varargin{2}代表可变参数列表的 ...

  2. 【黑金原创教程】【Modelsim】【第三章】理想就是美丽

    声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...

  3. oracle 存储过程返回结果集

    好久没上来了, 难道今天工作时间稍有空闲, 研究了一下oracle存储过程返回结果集. 配合oracle临时表, 使用存储过程来返回结果集的数据读取方式可以解决海量数据表与其他表的连接问题. 在存储过 ...

  4. Android APK反编译详解

    这段时间在学Android应用开发,在想既然是用Java开发的应该很好反编译从而得到源代码吧,google了一下,确实很简单,以下是我的实践过程. 在此郑重声明,贴出来的目的不是为了去破解人家的软件, ...

  5. SSH电力项目一 搭建Hibernate框架

    Hibernate所需要的基本文件: ElectText.java ElecText.hbm.xml hibernate.cfg.xml 第一步:创建测试表Elec_Text: create tabl ...

  6. [LeetCode] Maximum Subarray Sum

    Dynamic Programming There is a nice introduction to the DP algorithm in this Wikipedia article. The ...

  7. CentOS 部署openVPN

    一.openVPN工作原理 VPN技术通过密钥交换.封装.认证.加密手段在公共网络上建立起私密的隧道,保障传输数据的完整性.私密性和有效性.OpenVPN是近年来新出现的开放源码项目,实现了SSLVP ...

  8. Python量化常用函数

    # -*- coding: utf-8 -*- # @Author: fangbei # @Date: 2017-08-26 # @Original: price_str = '30.14, 29.5 ...

  9. imToken 测评通关攻略

    imToken 测评通关攻略 2017-10-19 imToken 在 1.3.3 版本新增了用户风险测评系统, 目的是为了让更多的用户了解钱包安全知识以及区块链的基本概念, 从某种程度上提升了整个区 ...

  10. PHP 错误日志

    display_errors 错误回显,一般常用语开发模式,但是很多应用在正式环境中也忘记了关闭此选项.错误回显可以暴露出非常多的敏感信息,为攻击者下一步攻击提供便利.推荐关闭此选项. display ...