命名空间不能直接包含字段或方法之类的成员是什么意思_Python 学习笔记之类与实例...

Python 学习笔记之类与实例

一、定义

1.1、定义

类 (class) 封装一组相关数据,使之成为一个整体,并使用一种方法持续展示和维护。

这有点像把零件组装成整车提供给用户,无须了解汽车的内部结构和工作原理,只要知道方向盘,刹车和油门这些外部接口就可以正常行驶。

类存在两种关系

  1. 继承(inheritance,is-a)自某个族类
    继承可以用来表达本车属于某厂的哪个车族系列,除了继承原车系的技术和优势,还可基于某些环境进行改进。
  2. 组合(composition,has-a)了哪些部件
    组合可用来表述该车使用了哪些零部件,比如最新的发动机。

类与模块的不同之处

  1. 类可生成多个实例。
  2. 类可被继承和扩展。
  3. 类实例的生命周期可控。
  4. 类支持运算符,可按需重载。

这些特性模块没有或者不需要,同时,模块粒度大,模块可用来提供游戏场景级别的解决方案,而类则是该场景下的特定家族和演员。

1.2、创建

定义类,以此为个体为例。关键字 class 同样是运行期指令,用于完成类型对象的创建。

  class User:pass
可在函数内定义,以限制其作用范围。

类型与实例

如果类在模块中定义,那么其生命周期与模块等同,如果被放在函数内,那么每次都是新建。即便名字和内容相同,也属于不同类型。

  def test():class X:passreturn X()​>>> a,b = test(),test()>>> a.__class__ is b.__class__Out[1]: False
函数内定义的类型对象,在所有实例死亡后,会被垃圾回收。

类型对象除了用来创建实例,也为所有实例定义了基本操作接口,其负责管理整个家族的可共享数据和行为目标。

实例只保存私有特征,其以内部引用从所属类型或其它所属祖先类查找所需的方法,用来驱动展现个体面貌。

dddc8d36edc51d0f9491cf6a154abff0.png

名字空间

类型有自己的名字空间,存储当前类型定义的字段和方法。这其中并不包括所继承的祖先成员,其同样以引用关联祖先类型,无须复制到本地。

  class A:a = 100                 #类字段def __init__(self, x):  #实例初始化方法self.x = x          #实例字段def_get_x(self):        #实例方法return self.xclass B(A):                 #继承自Ab = "hello"def __init__(self, x, y):super().__init__(self,x)    #调用父类的初始化方法self.y = ydef get_y(self):return self.y

c7a7160dbc9a565093a42345cee112d0.png

实例 instance o 会保存所有继承层次的实例字段,因为这些都属于其私有数据。

  >>> o = B(1,2)>>> print(A.__dict__){'a': 100,'__init__': <function A.__init__ at 0x109d04f28>, '_get_x': <function A._get_x at 0x109d046a8>, ...}>>> print(B.__dict__){'b': 'hello', '__init__': <function B.__init__ at 0x109d272f0>, 'get_y': <function B.get_y at 0x109d27378>, ...}

当通过实例或类访问某个成员时,会从当前对象开始(instance o 开始查找),依次由近到远向祖先类查找

(即 o --> class B --> class A 进行成员查找)。

如此做的好处就是祖先类的新增功能可以直接 【广播】给所有后代。

在继承层次的不同名字空间中允许有同名成员,并按顺序优先命中。

二、字段

依照所处空间不同,我们将字段分为类型字段实例字段

官方将成员统称为 Attribute,我们可按例将数据当做字段。

2.1、类型字段

【类型字段】在 class 语句块内直接定义,而实例字段必须通过实例引用(self)赋值定义。

仅从执行方式来看,无论实例方法存在于哪级类型,其隐式参数 self 总指向当前调用实例。

  class A:def test(self):             #self 总是指向引用的当前实例,这与继承层次无关print(self)self.x = 100class B(A):pass​if __name__=="__main__":o = B()print(hex(id(o)))print(o.test())0x109d2f358         <__main__.B object at 0x109d2f358>  
实例参数 self 只是约定成俗的名字,这类似于其它语言中的 this,换成 this 同样有效。

2.2、字段赋值

可使用赋值语句为类型实例添加的新字段

  class A:            pass​if __name__=="__main__":A.x = 100                   #新增类型字段print(A.x)print(vars(A))​'''100{x': 100, ...}'''

可一旦实例重新赋值,就将会在其名字空间建立同名字段,并会遮蔽原字段。

  a = A()a.b = 200print(a.b)print(vars(a))'''200{'b': 200}'''

2.3、私有字段

将私有字段暴露给用户是很危险的。因为无论是修改还是删除都无法截获,由此可能引发意外错误。因为语言没有严格意义上的访问权限设置,所以只好将它们隐藏起来。

如果成员名字以双下划线开头,但没有以双下划线结尾,那么编译器会自动对其重命名。

  class X:__table = "user"            #类型变量def __init__(self,name):self.name = name        #实例变量def get_name(self):return self.name
同时双下划线开头课结尾的,通常是系统方法,比如 __ init __ ,__ hash __ ,__ main __等。

所谓重命名,就是编译器附加了类型名称前缀。虽然这种做法不能真正阻止用户访问,但基于名字的约定也算一种提示。这种方式让继承类也无法访问。

重命名机制总是针对当前类型,继承类型无法访问重命名后的基类成员。

可将双下划线前缀改为单下划线,这样虽然不能自动重命名,不过提示作用依旧。

  class A:__name = "user"    #双下划线成员class B(A):def test(self):print(self.__name)​>>> B().test()'''AttributeError: 'B' object has no attribute '_B__name''''​class A:_name = "user"    #单下划线成员class B(A):def test(self):print(self._name)>>> B().test()'''user'''

三、属性

对私有字段会进行重命名保护,那公开字段如何处理呢?

问题是核心在于访问拦截,必须由内部逻辑决定如何返回结果。而属性(property)机制就是将读、写和删除操作映射到指定的方法调用上,从而实现操作控制。

  class C:def __init__(self, name):self.__name = name@propertydef name(self):                 #读return self.__name​@name.setterdef name(self, value):          #写self.__name = value         @name.deleterdef name(self):                 #删除raise AttributeError("can't delete attribute")​c = C("user")print(c.name)# user    c.name = "abc"print(c.name)# abcdel c.nameprint(c.name)#can't delete attribute
这种 @ 语法被称作装饰器(decorator)。
多个方法名必须相同,默认从读方法尅是定义属性,随后以属性名定义写和删除。
如果实现只读,或禁止删除,则只需去掉对应的方法即可。

四、方法

方法是一种特殊函数,其与特定对象绑定,用来获取或修改对象状态。

实际上,无论是对象构造,初始化,析构还是运算符,都以方法实现。根据绑定目标和调用方法的不同,方法可分为实例方法,类型方法,以及静态方法

名字以上下划线开始和结束的方法,通常有特殊用途,其由解释器和内部机制调用。

实例方法

实例方法与实例对象绑定,在其参数列表中,将绑定对象作为第一参数,以便在方法中读取或修改数据状态。在以实例引用调用方法时,无须显式传入第一实参,而由解释器自动完成。

官方建议参数名用 self,同样以 cls 作为类型方法的第一参数名。
  class W:def __init__(self, name):self.__name = namedef get(self):              #以实例引用调用,自动传入 self 参数return self.__namedef set(self, value):self.__name = value>>> w = W("python")>>> w.get()                 #忽略第一参数'''python'''

类型方法

类型方法用来维护类型状态,面向族群提供服务接口。除绑定的第一参数名称不同外,还需添加专门的装饰器,以便解释器将其实例方法区分开来。

  class D:__data = "D.data"@classmethod                #定义为类型方法def get(cls):               #解释器自动将类型对象 D 作为 cls 参数传入return cls.__data@classmethoddef set(cls, value):cls.__data = value>>> D.get()                     #同样忽略 cls 参数'''D.data'''

静态方法

静态方法,则更像是普通函数。其既不接收实例引用,也不参与类型处理,所以就没有自动传入第一参数。使用静态方法,更多原因是将类型作为一个作用域,或者当前类型添加便捷接口。

  class DES:def __init__(self, key):self.__key = keydef encrypt_bytes(self, value):return str(self.__key) + str(value)@staticmethoddef encrypt(key, s):return DES(key).encrypt_bytes(s.encode("utf-8"))>>> DES.encrypt("key", "value")'''keyb'value''''

特殊方法

下面又解释器自动调用,与对象生命周期相关的方法。

  1. __ new __:构造方法,创建对象实例
  2. __ init __:初始化方法,设置实例的相关属性
  3. __ del __:析构方法,实例被回收时调用

创建实例时,会先调用析构方法初始化方法

  class E:def __new__(cls, *args):            #与__init__接收相同的调用函数print("__new__", args)return super().__new__(cls)def __init__(self, *args):          ##self 由 __new__创建并返回print("__init__", args)>>> E(1,2)'''__new__ (1, 2)__init__ (1, 2)'''

如果 __ new __ 返回实例与 cls 类型不符,将导致 __ init __ 无法执行。

五、总结

学习到此,我总算把类的创建,属性和方法等弄清楚了,我最想强调一点,希望读者把 实例 self 参数弄明白,后续编码过程中使用较多。

还要清楚实例方法和静态方法的区别。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366408.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跨平台开发框架 Lynx 初探

跨平台开发是目前开发较热门的方向&#xff0c;React Native 在这方面取得了很大的成功&#xff0c;同时 Flutter 也获得了非常多的关注。React Native 采用 Web 框架开发并使用 Native UI 进行渲染&#xff0c;很大程度上降低了 Native 开发的门槛并且提高迭代的效率&#xff…

linux ubuntu 关于vim得一些基本命令

&#xff11;.vim显示行号 :set number 2. 快捷键 J 向下 K 往上 H 向左 L 向右 ctrlshiftT  打开新窗口 ctrlPage Down 所有vim窗口向下切换 ctrlPage Up 所有vim窗口向上切换 &#xff13;. 复制vim打开的内容 yy 复制光标所在行 2yy 复制光标所在行往下的两行 ....…

ajax包含mysql吗_php 实例ajax与mysql怎么只查询出一条数据?

http://www.runoob.com/php/php...使用这个实例操作之后为什么只显示一条数据&#xff0c;如何让符合条件的数据全部显示出来如&#xff0c;我使用的查询字段是yesterday_str&#xff0c;查询2017-04-18这个数据怎么样才能把2017-04-18包含这个的全部数据提取出来&#xff1f;p…

使用Servlet 3.0,Redis / Jedis和CDI的简单CRUD –第2部分

在本文中&#xff0c;我们将重点介绍CDI和Servlet 3.0。 您可以在此处看到第1部分。 让我们从CDI开始。 当我开始撰写源自该系列的文章时&#xff0c;我并没有考虑撰写CDI。 真诚地说&#xff0c;我以前从未使用过。 这篇文章的想法是使用jedis和servlet创建一个对象。 但是&a…

Safari支持Service Worker,PWA还有多久爆发?

作者 | 彭星 编辑 | 尾尾 在之前的文章《PWA 将带来新一轮大前端技术洗牌&#xff1f;》中&#xff0c;我们回顾了 Web 在移动时代遭遇的两大枷锁&#xff0c;并就PWA是否能真正弥补 Web 劣势进行了分析&#xff0c;同时&#xff0c;提出“根据当前的发展趋势&#xff0c;PWA…

安装python3 及virtual与virtualenvwrapper

安装python3 下载python源码包 网址&#xff1a;https://www.python.org/downloads/release/python-362/ 下载地址&#xff1a;https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tar.xz 安装python前的库环境&#xff0c;非常重要 yum install gcc patch libffi-devel py…

响应式设计与前端工程性

一&#xff1a;响应式的几个基本知识 字体选择 有衬线和无衬线&#xff0c;那种字体看自己的美学意识和考虑 透视比例与体验一致性保证&#xff08;人眼的位置&#xff09; 行高&#xff0c;字体大小&#xff0c;间距&#xff0c;要根据整个展示范围的透视比例合理的去规划pc 离…

aspx写入mysql_Asp.net用户登陆数据库验证与注册写入数据库

1.思路与效果图Index.aspx注册注册成功登陆登陆验证通过进入内容页1登陆没通过验证思路&#xff1a;首先建一个Sqlserver数据库Student,再建一个student表(name,pwd)存放用户名和密码。然后注册功能的实现&#xff1a;通过数据库插入信息到表的Sql语句来实现&#xff0c;成功提…

在WildFly中将Apache Camel和Spring添加为jboss模块

这些天&#xff0c;我在玩Wildfly &#xff0c; Apache Camel和Spring 。 在EAR / WAR之间进行通信的一种简单方法是使用Camel的direct-vm组件。 有或没有骆驼&#xff0c;有很多方法可以实现这一目标。 骆驼在WildFly中就像一个饰物&#xff0c;不需要任何额外的配置。 骆驼很…

页面体验提升小技巧—渐进式图片

前端性能方面有许多可优化的点&#xff0c;而这些优化带来的就是用户体验的提升。今天我们要聊的东西并不能给性能带来提升&#xff0c;但却能在一定程度上提升用户的体验。 参考博客 场景&#xff1a;在访问页面的时候如果图片较大或者网速慢的情况我们会看到图片加载起来是有…

php mysql无限分类排序_PHP 无限级分类、排序

lyk625358header(content-type:text/html;charsetutf-8);echo "";//-无限级排序,自己优化改良的,清除上次调用此函数后留下的静态变量的值$arr array(array(id>2,cname>分类2,parent_id>1),array(id>9,cname>分类9,parent_id>8),array(id>1,cn…

Java方法中的参数太多,第5部分:方法命名

在上一篇文章 &#xff08;有关处理Java方法中过多参数的系列文章的 第4部分 &#xff09;中&#xff0c;我将方法重载视为一种向客户提供需要较少参数的方法版本或构造函数的方法。 我描述了该方法的一些缺点&#xff0c;并建议从方法重载中摆脱出来以使用不同名称的方法至少可…

微信小程序搭配小白接口,自己没有服务器也能开发哦

这里将重点介绍&#xff0c;在自己没有服务器的情况下&#xff0c;如何在微信小程序里直接调用小白接口。 前提 假设你已经开通微信小程序&#xff0c;如果还没有&#xff0c;可前往微信公众平台开通&#xff1a;https://mp.weixin.qq.com 假设你已经开通小白接口&#xff0c…

LeetCode:34. 在排序数组中查找元素的第一个和最后一个位置

1、题目描述 给定一个按照升序排列的整数数组 nums&#xff0c;和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。 你的算法时间复杂度必须是 O(log n) 级别。 如果数组中不存在目标值&#xff0c;返回 [-1, -1]。 示例 1: 输入: nums [5,7,7,8,8,10], targ…

怎么将自己做好的网站发布到互联网上呢?

如何将自己的网站上传到网站空间。 1.需要有一个上传网站的软件&#xff0c;在这里推荐大家使用 FTP全称是flashfxp这个软件&#xff0c;这个功能功能齐全而且操作简单。大家可以先去下载一下这个软 件 2. 打开FTP&#xff0c;界面如下 3.我们要点击链接按钮&#xff0c;然后FT…

vue动态生成下拉框_vue+elementui 动态创建下拉框

v-for"(domain, index) in dynamicValidateForm.domains":label"‘站点‘ index":key"domain.id">v-for"item in testData":key"item.id":label"item.testName":value"item.id":disabled"item…

[贝聊科技]网页端「应用跳转」技术实现演变

本文作者&#xff1a;Mr.Luo &#xff0c;贝聊前端经理。本文同时发布于作者 个人博客 。 由于网页传播的便捷性&#xff0c;从网页向APP导流几乎是所有APP厂商都会采用的推广手段&#xff0c;具体来说就是在网页上提供一些触发点&#xff08;例如按钮、链接&#xff09;&#…

常见Java错误的十大列表(前100名!)

前10名名单非常受欢迎&#xff0c;有趣且内容丰富。 但是有很多&#xff01; 如何选择合适的&#xff1f; 这是一个元前10名列表&#xff0c;可帮助您找到前10名的前10名列表。 在更令人讨厌的笔记上&#xff1a; SELECT TOP 10 mistake FROM source1 UNION ALL SELECT TOP 10…

Ubuntu 16.04 下octave的使用入门

SciLab和octave是开源的且免费的矩阵计算工具&#xff0c;二者都有希望成为矩阵计算的新宠。相比之下&#xff0c; octave与MatLab的兼容性更高。octave遵循GPL协议&#xff08;GNU General Public License&#xff09;&#xff0c;用户可以单独发行octave或者包含在其产品中发…

hydra mysql 爆破_Hydra(爆破神器)使用方法

文本框 textarea 动态显示行数(简单文本编辑器)工作需求做一个文本编辑器简单的. 右边输入文字,左边会显示相应的代码行.清空也会变为1. 废话不多说上代码,自己理解. python中set使用In [2]: a set() # 常用操作1 In [3]: a Out[3]: set() In [4]: type(a) Out[4]: set In [5]…