Python类属性或实例属性的类型限制

Python类属性与实例属性详解 Python 中区分类属性和实例属性的设计是为了满足不同的需求和使用场景。这种区分使得代码更加灵活、清晰,并且能够提供更好的封装性和可维护性。类属性用于表示与整个类相关的数据,而实例属性则用于表示每个实例的特定信息。这样,我们可以将关注点分离开来,使得代码更易于理解、维护和扩展。在实际应用中,我们可以根据具体的情况,选择适当的属性类型来组织和管理代码。 阅读详情

0. 背景

在Python的大量类属性或是实例属性中,由于python语法的特性,属性并不带有类型,可以随意赋值,当然了也可以通过@property用来限制某个属性,但是对于需要大量重用代码的情况下,描述符会更有用。使用描述符,与其说是类型限制,不如说是赋值时的类型检查。问题解决的目标是:

针对某个自定义的类,自定义有目标类型(比如Integer, String,Float)的类属性或是实例属性。如果在初始化或赋值操作中,需要使得属性的类型发生了转化,则会出现Error。

1. 思路与方案

如果想创建一个具有类型限制的实例属性,可以以描述符(了解python描述符的用法)的形式定义其功能。实例如下:

# 使用描述符来对以Integer类型为属性的限制
class Integer(object):

    def __init__(self, name):
        self.name = name

    def __get__(self, instance, cls):
        if instance is None:
            return self
        else:
            return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, int):
            raise TypeError("Expected an int")
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        del instance.__dict__[self.name]

所谓的描述符就是以特殊方法__get__(),__set__(),__delete__()的形式实现了三个核心的属性访问操作(对于与get,set和delete)的类。这些方法通过接受类实例作为输入来工作。之后,底层的实例字典会根据需要适当地进行调整。

要使用一个描述符,我们把描述符的实例放置在类的定义中作为类变量来用。示例如下:

# 属性x,y以Integer类为类型的使用
class Point(object):
    x = Integer('x')
    y = Integer('y')

    def __init__(self, x, y):
        self.x = x
        self.y = y

当这么做时,所有针对描述符属性(即,这里的x或y)的访问都会被__get__(),__set__(),__delete__()方法所捕获

if __name__ == '__main__':
    p = Point(2,3) # 调用Point.__init__,进而调用 Point.x.__set__(),Point.y.__set__()
    print p.x # 调用Point.x.__get__()

    p.y = 5 # 调用Point.y.__set__()
    p.x = 2.3

运行的结果是:

C:\Python27>python C:\Users\snwang\Desktop\wsn_attr.py
2
Traceback (most recent call last):
  File "C:\Users\snwang\Desktop\wsn_attr.py", line 36, in <module>
    p.x = 2.3
  File "C:\Users\snwang\Desktop\wsn_attr.py", line 17, in __set__
    raise TypeError("Expected an int")
TypeError: Expected an int

每个描述符方法都会接受被操纵的实例作为输入。要执行所请求的操作,底层的实例字典(即__dict__属性)会根据需要适当的进行调整。描述符的self.name属性会保存字典的key,通过这些key可以找到存储在实例字典中的实际数据。

2. 方案深化

上述的方案有一些不足:作为Integer类型的已经写完了,如果我们想要写String,或是Float,这要我们又要重新写一遍类似的代码。遵从代码重用原则,我们应该建立一个描述符基类,然后让这些类型继承它。

下面的代码使用描述符实现了一个类型系统以及对值进行检查的框架:

# 描述符基类,用于类型检查
class Typed(object):

    def __init__(self, name, expected_type):
        self.name = name
        self.expected_type = expected_type

    def __get__(self, instance, cls):
        if instance is None:
            return self
        else:
            return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, self.expected_type):
            raise TypeError("Expected " + str(self.expected_type))
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        del instance.__dict__[self.name]

创建了描述符类之后,如果属性是int类型的,那么只需设置expected_type=int,str,float同理。

接下来我们需要写一个类装饰器,用来装饰自定义的类:在自定义类之前,将类属性设置为某特定类型的Typed实例,代码如下:

#类装饰器,用来装饰自定义的类, 且将类属性设置为某特定类型的Typed实例
def typeassert(**kwargs):
    def decorate(cls):
        for name, expected_type in kwargs.items():
            # 将名字name和期望类型创建一个Typed实例
            iTyped = Typed(name, expected_type)
            # 将名字name和iType,设置到cls中,作为对应cls.__dict__中的key,value
            setattr(cls, name, iTyped)
        return cls
    return decorate

然后就是使用这个类装饰器的测试代码:

# 例子使用,装饰器使用
    @typeassert(name=str, shares=int, price=float)
    class Stock(object):
        def __init__(self, name, shares, price):
            self.name = name
            self.shares = shares
            self.price = price

    # 调用了 Stock.name.__set__(s, 'csdn')
    #       Stock.shares.__set__(s, 529)
    #       Stock.name.__set__(s, 22.08)
    s = Stock(name = 'csdn', shares = 529, price = 22.08)

    # 调用了 Stock.name.__get__(s, Stock)
    #       Stock.shares.__get__(s, Stock)
    #       Stock.price.__get__(s, Stock)
    print s.name, str(s.shares), str(s.price)

    # 调用了Stock.shares.__set__(s, 'this_is_a_str'),但是期望是int类型,所以会有error
    s.shares = 'this_is_a_str'

输出结果:

C:\Python27>python C:\Users\snwang\Desktop\typeassert.py
csdn 529 22.08
Traceback (most recent call last):
  File "C:\Users\snwang\Desktop\typeassert.py", line 56, in <module>
    s.shares = 'this_is_a_str'
  File "C:\Users\snwang\Desktop\typeassert.py", line 18, in __set__
    raise TypeError("Expected " + str(self.expected_type))
TypeError: Expected <type 'int'>

最后,应该强调的是,如果只是想访问某个特定的类中的一种属性,并对此做定制化处理,那么最好不要编写描述符来实现。对于这个任务,用@property属性方法来完成会更加简单。当在需要大量重用代码的情况下,描述符会更加有用,例如,我们希望在自己的代码中大量使用描述符提供的功能,或者将其作为库来使用。

3. 总结

本文主要讲述了怎样使用描述符来对类属性进行类型限制。若想查看上面的例子全部代码,请移步我的github https://github.com/csdz/SnapToSnap/tree/master/descriptor,也欢迎关注。

Xilinx FPGA平台GTX简易使用教程(一)GTX基础知识 理解GTX的必备姿势,学起来! 阅读详情

相关推荐

染色体外环状DNA:肿瘤研究新方向

染色体外环状DNA(ecDNA)是癌症中活化原癌基因扩增的主要方式。区别于常染色体,这类生物大分子主要以环状的形式存在于细胞核当中,长度分布在103-106数量级,无中心粒。ecDNA序列中包含一个或者多个基因与调控元件,结构开放,转录活性强,相比于在棒状染色体结构基因,ecDNA的生物功能活性更强。癌症中,成环的基因区域拷贝数往往增高,而超过一半的高拷贝数事件是ecDNA驱动生成。...

blackjimmy的博客 765

Python3 类

类变量 & 实例变量 self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类 class Test: w = 10 # 类变量 def __init__(self, k): Test.h = 50 # 类变量 self.k = k # 实例变量 def prt(self): print(self) print(self.__class__) # 内存:类{Test, w=10}

Sigmoid 1492

U型槽微带贴片天线:从理论公式到带宽扩展实战

本文深入探讨了U型槽微带贴片天线的设计与带宽扩展实战。针对传统微带天线带宽窄的痛点,详细解析了通过引入U型槽形成双谐振点以拓宽带宽的原理,并提供了从MATLAB理论计算、ANSYS HFSS仿真建模到参数优化的一站式工程指南。文章还分享了多种带宽扩展组合技巧及仿真与实测避坑经验,助力射频工程师设计出高性能的宽带微带天线。

weixin_29168153的博客 447

pandas raise TypeError(‘expected ‘ + str(self.expected_type)) TypeError: expected <class ‘str‘>

这个问题在pandas1.1以上应该都会有,我的原因是excel最后两行是这样的,不是个规范的格式 这个不规范的格式在之前可以用参数skipfooter=2轻松处理,但在较新的版本就会出现如题的错误。 另一个原因是pandas更新了引擎,从xlrd => openpyxl xlrd因为安全性不高,在较新版本放弃了对xlsx格式的支持,pandas也将引擎换到openpyxl。 解决方法是:pandas退回1.0.1版本,xlrd退回1.2.0版本 pip install pandas==1.0.1

小白tree的博客 5560

RenderDoc实战:5分钟搞定安卓Vulkan应用抓帧(含常见连接失败排查)

本文详细介绍了如何使用RenderDoc工具对安卓Vulkan应用进行抓帧分析,包括环境配置、完整抓帧流程及常见连接问题的解决方案。通过实战案例和高级技巧,帮助开发者快速定位渲染问题和性能瓶颈,提升移动图形开发效率。

weixin_28318011的博客 281

实战指南:在摩尔线程GPU上部署AI模型的完整流程

本文提供了一份详尽的实战指南,手把手教你如何在摩尔线程GPU上成功部署AI模型。内容涵盖从驱动安装、Docker环境配置,到核心的代码适配与模型运行全流程,并分享了性能调优技巧与常见避坑方法,旨在帮助开发者高效利用国产硬件进行AI应用开发。

weixin_29271263的博客 541

python修改属性默认值_python3 类中 怎么将方法的默认参数设置为属性?

这里搞不懂说明你对Python代码的执行理解得不够。在Python中,我们可以粗略的将一段代码被执行的时间分为“import time”和“run time”。在import time被执行的代码,顾名思义,大多数情况是在被import时执行的代码,实际上并不一定非在被import时被执行。之所以我们这样称呼它,是因为在这个时间被执行的代码通常都是类和函数的定义,而这样的代码通常都写在单独的模块中...

weixin_39979167的博客 354

保姆级教程:手把手带你玩转英飞凌TC397开发板的板载资源(CAN FD、LCD、SD卡)

本文提供英飞凌TC397开发板的全面开发指南,涵盖CAN FD通信、LCD显示、SD卡文件系统和以太网通信等核心功能。通过详细的代码示例和硬件连接说明,帮助开发者快速上手并充分利用开发板的丰富资源,实现高效嵌入式系统开发。

weixin_33726313的博客 241

Python面对对象之初始化方法(__int__方法)

学习__int__方法

Redhat_yan 4149

从Datasheet到可用的Verilog模块:手把手教你为N25Q128 SPI Flash写状态机驱动

本文详细介绍了如何从Datasheet到实现可用的Verilog模块,手把手教你为N25Q128 SPI Flash编写状态机驱动。文章涵盖SPI Flash的核心工作机制、数据手册解析方法、Verilog状态机设计实践以及调试与性能优化技巧,特别适合FPGA开发者和硬件设计工程师参考。

weixin_30596023的博客 176

利用Docker Compose简化openGauss多节点容器化部署

本文详细介绍了如何利用Docker Compose简化openGauss多节点容器化部署,从环境准备到配置文件编写,再到集群部署与验证,提供了一套完整的解决方案。通过Docker Compose,原本复杂的手动部署流程被大幅简化,显著提升了部署效率和可靠性,特别适合企业级开源数据库的高可用架构需求。

weixin_30338481的博客 60

python类定义默认值为none_python non无默认值(python non None default values)

Programmer A writes the following function:def compute_value(threshold = sys.float_info.max):...return valuewhich has the optional parameter threshold which in a natural way has the maximum float valu...

weixin_39981041的博客 294

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

python描述符与实例属性_Python类属性或实例属性的类型限制

0. 背景在Python的大量类属性或是实例属性中,由于python语法的特性,属性并不带有类型,可以随意赋值,当然了也可以通过@property用来限制某个属性,但是对于需要大量重用代码的情况下,描述符会更有用。使用描述符,与其说是类型限制,不如说是赋值时的类型检查。问题解决的目标是:针对某个自定义的类,自定义有目标类型(比如Integer, String,Float)的类属性或是实例属性。如果...

weixin_34741145的博客 346

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

python中的类属性、实例属性、类方法、实例方法

定义类 class Person(): pass 创建实例 xiaoming = Person() xiaohong = Person() 实例属性 xiaoming = Person() xiaoming.name = xiaoming xiaoming.age = 24 xiaoming.sex = man xiaohong = Person() xiaohong.n...

loner_fang的博客 5万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Python进阶 - 类的属性 实例属性与类属性的区别

Python类属性与实例属性解析 本文深入探讨了Python中类的属性机制,重点区分了实例属性与类属性的关键区别: 基本概念: 实例属性:在__init__中通过self定义,每个实例独立拥有 类属性:直接定义在类体内,所有实例共享 核心区别: 实例属性存储在各实例的__dict__中,类属性存储在类的__dict__中 修改类属性会影响所有实例,而实例属性修改只影响当前实例 属性查找机制: Python会按照"实例→类→父类"的顺序查找属性 实例属性会遮蔽同名的类属性 常见陷阱: 避免将可变对象作为类属性

千淘万漉虽辛苦,吹尽狂沙始到金 8102

python基础------类属性和实例属性

目录     一、定义 (一).定义 (二).使用方式 (三).注意 二、类属性和实例属性 (一)不可变数据类型 1.定义一个课程类,定义一个language不可变数据类型, (二)可变数据类型 1.定义一个课程类,定义一个language_lst=['pytjon']可变数据类型, 三、封装特性 1.封装定义: &lt;1&gt;未封装之前 &lt;2&gt;封装_...

石马的农的博客 433

python 基础知识 | 类属性和实例属性

目录类属性和实例属性类属性实例属性自定义类属性和实例属性通过类方法创建类属性属性的访问限制@property 类属性和实例属性 python中类和实例都维护一个__dict__字典,用来存放方法和属性,可以通过dir()函数查看,下面直接通过代码去说明类属性和实例属性的区别。 class Student(): # 类属性 num = '类属性' def __init__(sel...

遇卿 379

类,实例;访问限制;实例属性,类属性

类:类是抽象的模板。 实例:实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法 如何定义一个类?如下,什么叫做实例化? 如下 class Avengers(object):#继承总的基类 pass #定义完一个类 avengers=Avengers()#称之为实例化 变量avengers指向的就是一个Avengers的实例,每个object的地址都不一样,而Student本身则是一个类。 ...

m0_37976933的博客 1229

Python 类属性以及封装特性

目录 一,类属性和实例属性 练习1 练习2 练习3 练习4 二、封装特性 1,什么是封装 2、私有属性 练习1 练习2 练习3 3、私有方法 4,私有化封装后的限制 一,类属性和实例属性 实例属性:在实例对象中定义的属性 类属性(静态属性):在类对象(也就是类)中定义的属性,并且多个实例对象之间共享一份类属性。 类属性的使用方法:类名.类属性  或者   对象名....

人生苦短。。。 1438

python动态添加属性(对象属性,类属性) __slots__对动态添加属性及方法的限制作用

** 1,python动态添加属性(对象属性,类属性) ** 1,python是动态类型语言:可以在运行中改变自身结构,动态添加/删除属性和方法,删除函数 2,也是强类型语言:变量的类型可以在运行之后,任意变量,不需要强制转换 动态添加实例属性和类属性的演示如下: class Person: def __init__(self, name, age): self.name ...

嘎嘎_哈 6618

Python笔记(十八)_私有属性、实例属性、类属性

私有属性 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,就变成了一个私有属性,只有内部可以访问,外部不能直接访问或修改。 这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮 那如果想让外部代码获取私有属性该怎么办? 修改内部代码:可以给类增加访问方法(return self.__name)和修改方法(self.__score=scor...

weixin_30699831的博客 542

Python 探究类属性和实例属性的使用

类属性和实例属性 尽量把需要用户传入的属性作为实例属性,而把同类都一样的属性作为类属性。 实例属性在每创造一个类是都会初始化一遍 不同的实例的实例属性可能不同,不同实例的类属性都相同。 实例属性 在__init__(self,…)中初始化 内部调用时都需要加上self. 外部调用时用“对象名.属性名”调用 类属性 在__init__()里初始化 在内部用classname.类属性名调用 外部既...

小鹏AI 538

python:类属性、实例属性、类方法、实例方法、静态方法

参考1:https://www.cnblogs.com/gengyufei/p/11370026.html 参考2:https://blog.youkuaiyun.com/loner_fang/article/details/80877491 类属性   直接在类中创建的属性就叫类属性。    类属性就相当于全局变量,实例对象共有的属性,而实例对象的属性为实例对象自己私有。   类属性就是类对象所拥有的属性,它被所有类对象的实例对象(实例方法)所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点

微风❤水墨 653

Python 类与对象编程详解三(类属性、实例属性)

上一篇:Python 类与对象编程详解二(成员保护和访问限制) 目录类属性属性的定义操作类属性的三种方法属性存在的意义操作类属性的方法使用@property装饰器操作类属性通过@property装饰器对属性的取值和赋值加以控制使用python内置函数操作属性。 类属性 属性的定义 python中的属性其实是普通方法的衍生。 操作类属性的三种方法 1.使用@property装饰器操作类属性。 2.使...

weixin_45144837的博客 1024

python3 类属性、实例属性、类方法、对象方法、静态方法

每次看到面向对象,我就看得有点头大,今天把这些都记下来,便于以后记忆。先放一段代码 class Person(object): # 限定Person对象只能绑定_name, _age和_gender属性 __slots__ = ('_name', '_age', '_gender') count = 0 def __init__(self, name, age): ...

calmuse的博客 821
上一篇: Python Types and Objects
下一篇: 自动安装Python第三方库
tab_space
博客等级 码龄11年 91粉丝 29原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值