如何通过一些骚操作有效的控制Python类

平时工作中,能用到的类基本都是可变的,无论是实例的属性,还是类的属性,也正是因为这样,所以python也是一个“鸭子类型”的编程语言。

今天给大家看看python类的不同面,“不可变”

首先先来看下普通的类,我们都是怎么操作的

>>> class A:
...     pass
... 
>>> a = A()
>>> a.abc
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'A' object has no attribute 'abc'
>>> a.abc = 1
>>> a.abc
1

上面这段代码很简单,对于你来说一定也不陌生,在我们需要的时候动态的添加属性,这也是我们用python很爽的地方。

那么这个时候,如果这个类是个关键类,或者只是个只读类,如何才能组织这些动态的,不受控制的添加呢?

>>> class B:
...     __slots__ = ['papapa']
...     
...     def __init__(self, papapa):
...         super().__setattr__('papapa', papapa)
...         
...     def __setattr__(self, name, value):
...         raise AttributeError(f'{self.__class__} has no attribute {name}')
...     
>>> b = B('fanbingbing')
>>> b.papapa
'fanbingbing'
>>> b.papapa = 'linzhiling'
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 8, in __setattr__
AttributeError: <class 'B'> has no attribute papapa
>>> b.__dict__
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'B' object has no attribute '__dict__'
>>> b.abc = 123
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 8, in __setattr__
AttributeError: <class 'B'> has no attribute abc

这里的关键点有2个:

  1. __slots__ 方法,在类中,使用__slots__方法可以控制类的属性和方法,在定义完类后,我对b.__dict__做了一个查询,目的就是告诉大家,__slots__会替换掉__dict__,而__dict__就是类和实例存储属性的地方。 但是大家一定要注意,使用__slots__是有风险的,由于强制限制了__dict__的使用,那么你要添加任何方法和属性的时候就得重写这个类了,并且继承B类的子类,也需要重写__slots__方法。 所以通过__slots__,我们限制了实例属性的任意添加。
  2. __setattr__方法,我们在__init__这个构造函数中,添加了这个方法,目的是为了设置一个在__slots__中存在的属性的值,而在__setattr__函数中,我们重写了他,致使对任意类和实例属性进行修改的时候,都会进行异常抛出。 所以通过__setattr__,我们限制了实例属性“papapa”的任意修改。

如果对__slots__属性不理解的同学,推荐大家一个去处:

https://stackoverflow.com/questions/472000/usage-of-slots

写的很好。

如果你对今天的内容还感兴趣的话,何不点个赞再走呢?如果感兴趣到想赞赏我,就不要犹豫啦~


原文发布于微信公众号 - 猿媛牧场(xpchuiit)

原文发表时间:2018-06-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏F_Alex

在Java中谈尾递归--尾递归和垃圾回收的比较(转载)

2435
来自专栏余林丰

Java中net.sf.json包关于JSON与对象互转的坑

  在Web开发过程中离不开数据的交互,这就需要规定交互数据的相关格式,以便数据在客户端与服务器之间进行传递。数据的格式通常有2种:1、xml;2、JSON。通...

3765
来自专栏Java技术栈

90 % Java 程序员被误导的一个性能优化策略

我们经常看到一些 Java 性能优化的书或者理念,说不要在循环内定义变量,这样会占用过多的内存影响性能,而要在循环外面定义。接触 Java 这么久以来,相信很多...

1222
来自专栏用户2442861的专栏

json格式

  1. “名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),记录(reco...

2682
来自专栏老马说编程

(92) 函数式数据处理 (上) / 计算机程序的思维逻辑

上节我们介绍了Lambda表达式和函数式接口,本节探讨它们的应用,函数式数据处理,针对常见的集合数据处理,Java 8引入了一套新的类库,位于包java.uti...

1926
来自专栏Python小白进阶之旅

Python面试必备,看完轻轻松松拿到10k

平时我们几乎不可能用到的东西,像那些类里面的魔法方法,你还记得几个,这些可都是面试必备啊~

4258
来自专栏阿凯的Excel

Python读书笔记25(类的继承)

谈类的使用,怎能缺失类的继承!类的继承可以大大简化代码编辑工作。 为啥这么说呢! 因为一个类继承另外一个类的时候,可以自动获得另一个类的所有属性和方法! 原有的...

3506
来自专栏老司机的技术博客

人人都能学会的python编程教程9:dict和set

dict和我们小时候用的字典很像,如果你想查一个汉字,你只需要根据某一个拼音就可以很快速的查询到它。

6248
来自专栏前端新视界

立即执行函数表达式(IIFE)

原文:immediately-invoked-function-expression 译者:nzbin 也许你还没有注意到,我是一个对术语比较坚持的人。因此...

2165
来自专栏Pythonista

封装与扩展性

封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码...

953

扫码关注云+社区

领取腾讯云代金券