python高级属性 用法 编程_python高级编程之面向对象高级编程

1 面向对象编程

面向对象这节比较简单,就稍微总结几个特殊的点。

特殊方法__init__前后分别有两个下划线,__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去。

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。

需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。

多态:当我们需要传入Dog、Cat、Tortoise……时,我们只需要接收Animal类型就可以了,因为Dog、Cat、Tortoise……都是Animal类型,然后,按照Animal类型进行操作即可。由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态。

“鸭子特性”:对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。

对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了。

2 面向对象高级编程

2.1 获取对象信息

2.1.1 type()

判断对象类型,使用type()函数:

>>> type(123)

>>> type('str')

>>> type(None)

如果要判断一个对象是否是函数可以使用types模块中定义的常量:

>>> import types

>>> def fn():

... pass

...

>>> type(fn)==types.FunctionType

True

>>> type(abs)==types.BuiltinFunctionType

True

>>> type(lambda x: x)==types.LambdaType

True

>>> type((x for x in range(10)))==types.GeneratorType

True

对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。

2.1.2 dir()

如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:

>>> dir('ABC')

['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']

类似__xxx__的属性和方法在Python中都是有特殊用途的,比如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法,所以,下面的代码是等价的:

>>> len('ABC')

3

>>> 'ABC'.__len__()

3

仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:

>>> class MyObject(object):

... def __init__(self):

... self.x = 9

... def power(self):

... return self.x * self.x

...

>>> obj = MyObject()

紧接着,可以测试该对象的属性:

>>> hasattr(obj, 'x') # 有属性'x'吗?

True

>>> obj.x

9

>>> hasattr(obj, 'y') # 有属性'y'吗?

False

>>> setattr(obj, 'y', 19) # 设置一个属性'y'

>>> hasattr(obj, 'y') # 有属性'y'吗?

True

>>> getattr(obj, 'y') # 获取属性'y'

19

>>> obj.y # 获取属性'y'

19

如果试图获取不存在的属性,会抛出AttributeError的错误:

>>> getattr(obj, 'z') # 获取属性'z'

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'MyObject' object has no attribute 'z'

可以传入一个default参数,如果属性不存在,就返回默认值:

>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404

404

也可以获得对象的方法:

>>> hasattr(obj, 'power') # 有属性'power'吗?

True

>>> getattr(obj, 'power') # 获取属性'power'

>

>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn

>>> fn # fn指向obj.power

>

>>> fn() # 调用fn()与调用obj.power()是一样的

81

2.2 使用__slots__

如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:

class Student(object):

__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

然后,我们试试:

>>> s = Student() # 创建新的实例

>>> s.name = 'Michael' # 绑定属性'name'

>>> s.age = 25 # 绑定属性'age'

>>> s.score = 99 # 绑定属性'score'

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'Student' object has no attribute 'score'

2.3 使用@property

在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是没办法检查参数,导致可以随便给属性赋值。

对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:

class Student(object):

@property

def score(self):

return self._score

@score.setter

def score(self, value):

if not isinstance(value, int):

raise ValueError('score must be an integer!')

if value < 0 or value > 100:

raise ValueError('score must between 0 ~ 100!')

self._score = value

@property的使用方法是:把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作。

>>> s = Student()

>>> s.score = 60 # OK,实际转化为s.set_score(60)

>>> s.score # OK,实际转化为s.get_score()

60

>>> s.score = 9999

Traceback (most recent call last):

...

ValueError: score must between 0 ~ 100!

注意到这个神奇的@property,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。

还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性。

2.4 多重继承

在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。Python允许使用多重继承,这种设计通常称之为MixIn。

MixIn的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系。

2.5 定制类

后面用到实际例子时再补充。

2.6 使用枚举类

当我们需要定义常量时,一个办法是用大写变量通过整数来定义,例如月份:

JAN = 1

FEB = 2

MAR = 3

...

NOV = 11

DEC = 12

好处是简单,缺点是类型是int,并且仍然是变量。

更好的方法是为这样的枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例。Python提供了Enum类来实现这个功能:

from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

这样我们就获得了Month类型的枚举类,可以直接使用Month.Jan来引用一个常量,或者枚举它的所有成员:

for name, member in Month.__members__.items():

print(name, '=>', member, ',', member.value)

value属性则是自动赋给成员的int常量,默认从1开始计数。

如果需要更精确地控制枚举类型,可以从Enum派生出自定义类:

from enum import Enum, unique

@unique

class Weekday(Enum):

Sun = 0 # Sun的value被设定为0

Mon = 1

Tue = 2

Wed = 3

Thu = 4

Fri = 5

Sat = 6

@unique装饰器可以帮助我们检查保证没有重复值。

2.7 使用元类

type()函数可以查看一个类型或变量的类型,例如Hello是一个class,它的类型就是type,而h是一个实例,它的类型就是class Hello。type()函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object)...的定义。

我们说class的定义是运行时动态创建的,而创建class的方法就是使用type()函数。通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class:

>>> def fn(self, name='world'): # 先定义函数

... print('Hello, %s.' % name)

...

>>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class

>>> h = Hello()

>>> h.hello()

Hello, world.

>>> print(type(Hello))

>>> print(type(h))

要创建一个class对象,type()函数依次传入3个参数:

class的名称;

继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;

class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。

2.7.1 metaclass

除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。metaclass,直译为元类,简单的解释就是:当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。

但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。连接起来就是:先定义metaclass,就可以创建类,最后创建实例。

所以,metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。

先看一个简单的例子,这个metaclass可以给我们自定义的MyList增加一个add方法。定义ListMetaclass,按照默认习惯,metaclass的类名总是以Metaclass结尾,以便清楚地表示这是一个metaclass:

# metaclass是类的模板,所以必须从`type`类型派生:

class ListMetaclass(type):

def __new__(cls, name, bases, attrs):

attrs['add'] = lambda self, value: self.append(value)

return type.__new__(cls, name, bases, attrs)

有了ListMetaclass,我们在定义类的时候还要指示使用ListMetaclass来定制类,传入关键字参数metaclass:

class MyList(list, metaclass=ListMetaclass):

pass

当我们传入关键字参数metaclass时,魔术就生效了,它指示Python解释器在创建MyList时,要通过ListMetaclass.__new__()来创建,在此,我们可以修改类的定义,比如,加上新的方法,然后,返回修改后的定义。__new__()方法接收到的参数依次是:

当前准备创建的类的对象;

类的名字;

类继承的父类集合;

类的方法集合。

测试一下MyList是否可以调用add()方法:

>>> L = MyList()

>>> L.add(1)

>> L

[1]

而普通的list没有add()方法:

>>> L2 = list()

>>> L2.add(1)

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'list' object has no attribute 'add'

使用元类这块比较复杂,等楼主后面涉及到这块的实际例子再来补充这块。

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

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

相关文章

1命名规则 sentinel_Alibaba Sentinel 规则参数总结

本文总结了Alibaba Sentinel各种规则的参数。基于Sentinel 1.6.2编写&#xff0c;未来如果本文不再适用&#xff0c;可自行点击每一节 参考 一览的链接前往查看如何配置。一、流控规则1.1 配置1.2 参数Field说明默认值resource资源名&#xff0c;资源名是限流规则的作用对象cou…

java文件读写类及其用法介绍

见链接&#xff1a;转载于zhangbinu的博客

公共界面_公共建筑东营市档案馆能耗计量分析系统

摘要&#xff1a;本文介绍东营市档案馆能耗管理系统&#xff0c;采用智能电力仪表采集配电现场的各种电参量&#xff0c;仪表就地组网后通过现场总线通讯并远传至后台&#xff0c;通过Acrel-5000型建筑能耗监测系统实现配电回路用电的监测分析。关键词&#xff1a;大型公共建筑…

IDEA、pycharm白嫖攻略

本方法仅适用于高校大学生 JetBrains系列下的idea、pycharm优秀的代码提示让人爱不释手&#xff0c;但是相比较eclipse&#xff0c;idea的巨大缺点就是&#xff1a;要收费。 我看到身边的许多同学为了使用idea、pycharm而到处搜索激活码或者破解软件 &#xff0c;但是激活码还是…

com.alibaba.easyexcel导出指定的列_使用Python导入导出Excel表格

这篇文章的目的是讲解使用python导入导出Excel表格&#xff0c;目前还不涉及数据处理&#xff0c;主要实现为数据的展示。第一步&#xff0c;准备材料python3.8的安装包一个Excel表格第二步&#xff0c;安装软件python可以采用默认安装的方式&#xff0c;安装完之后把python和p…

2021-08-10 HDFS Web报错Couldn‘t preview the file.

在查看文件内容时&#xff0c;在红框位置出现报错“Couldn’t preview the file” 解决方法 第一步&#xff1a;修改hdfs-site.xml&#xff0c;添加配置信息 <property><name>dfs.webhdfs.enabled</name><value>true</value> </property&…

2021-08-10 maven配置阿里云仓库

方式一&#xff1a;全局配置 可以添加阿里云的镜像到maven的setting.xml配置中&#xff0c;这样就不需要每次在pom中&#xff0c;添加镜像仓库的配置&#xff0c;在mirrors节点下面添加子节点&#xff1a; <mirror><id>nexus-aliyun</id><mirrorOf>ce…

大橙子_橙子皮养花太棒了,酸性大,肥力足,比花肥强10倍

随着社会的不断发展&#xff0c;现在越来越多的人都喜欢在家里养花。在家里养花&#xff0c;可以装点居室&#xff0c;让我们家里更温馨漂亮&#xff0c;而且我们在养花的时候也能培养我们的兴趣&#xff0c;也有利于我们的身心健康。其实养花最主要的就是要补充充足的养分&…

hive启动报错:Exception in thread “main“ java.lang.NoSuchMethodError: com.google.common.base.Precondition

报错如下 Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V at org.apache.hadoop.conf.Configuration.set(Configuration.java:1380) ... at org.apache.ha…

adaptivitypara设置选0还是1_喝牛奶,选全脂还是低脂?家里人能不能喝同1种牛奶?...

年龄大的人&#xff0c;还记得&#xff0c;当年&#xff0c;牛奶是限量供应的&#xff0c;家里有婴儿或病人&#xff0c;才能得到1张卡&#xff0c;每天按时在街边等候&#xff0c;凭卡可以买到半斤掺水的牛奶。牛奶&#xff0c;被誉为接近完善的食品&#xff0c;其中所含的蛋白…

Centos8修改mysql密码

第一步&#xff1a;修改配置文件免密码登录mysql 进入文件&#xff1a;vi /etc/my.cnf文件末尾添加skip-grant-tables重启mysql 第二步: 免密码登录mysql 输入mysql登录&#xff1a; 进入数据库&#xff0c;输入&#xff1a; use mysql&#xff1b;查看root用户信息&#xf…

aop的实现原理_非Spring管理Bean如何添加AOP呢?

前几天有个朋友问了一个问题&#xff0c;觉得可以给大家分享一下。问题如下图归其根本这是个历史项目&#xff0c;里面有很多的类并没有交给spring管理&#xff0c;但现在需要统一添加日志。面对这样的问题&#xff0c;其实只要了解AOP的原理&#xff0c;就会有多种方法。AOP都…

什么从什么写短句_2020抖音文案短句:爱情、励志、伤感合集,值得收藏!

视频火不火&#xff0c;一半看文案&#xff01;想知道爆款视频的文案都是什么吗&#xff1f;想知道爆款文案的套路吗&#xff1f;今天&#xff0c;我就给大家整理了近期抖音爆款短视频的文案——爱情、励志、伤感短句&#xff0c;句句深入人心&#xff0c;赶紧来看看吧&#xf…

插入数据的时候出现错误:Error during job, obtaining debugging information…

插入数据的时候出现错误:Error during job, obtaining debugging information… 原因&#xff1a; Javaf堆内存不足 解决办法 修改为本地模式 set hive.exec.mode.local.autotrue;

win10更新失败,怎么删除临时文件下面的更新

首先按下WINR&#xff0c;然后在运行中输入services.msc 回车在服务中找到Windows update服务&#xff0c;右键点击停止然后打开文件夹C:\Windows\SoftwareDistribution\DownloadSoftwareDistribution\Download文件夹下就是更新后留下来的更新文件了&#xff0c;全部删除吧删除…

::在sql语句中是什么写法_不懂就问:SQL 语句中 where 条件后 写上1=1 是什么意思...

程序员在编程过程中&#xff0c;经常会在代码中使用到“where 11”&#xff0c;这是为什么呢&#xff1f;SQL注入初次看到这种写法的同学肯定很纳闷&#xff0c;加不加where 11&#xff0c;查询不都一样吗&#xff1f;例如&#xff1a;select * from customers; 与 select * fr…

U盘:对于目标文件系统,文件过大放不到u盘里

问题描述&#xff1a;从电脑复制粘贴一个11G的压缩包时&#xff0c;提示"对于目标文件系统&#xff0c;文件过大放不到u盘里" 原因&#xff1a;U盘的文件格式为FAT32&#xff0c;转为NTFS格式才支持大文件复制。 解决方法&#xff1a; 格式化为NTFS格式 U盘卷符名为…

django 集成个推_持续集成CircleCI vs Travis CI vs Jenkins

Continuous Integration. CircleCI vs Travis CI vs Jenkins​hackernoon.com持续集成(CI)的定义及其主要目标持续集成(CI)是一种软件开发实践&#xff0c;它基于将代码频繁集成到共享代码仓中。 然后通过自动构建(automated build)验证每个签入(Check-In)。持续集成(CI)的主要…

org.apache.hadoop.security.AccessControlException: Permission denied: user=anonymous, access=EXECUTE

直接在hdfs文件系统上修改supergroup的权限&#xff0c;解决问题 [roothadoop001 hadoop-3.1.3]# hdfs dfs -chmod -R 777 /tmp

战双帕弥什自抽号怎么使用_战双帕弥什新S冰露怎么玩《战双帕弥什》新S冰露玩法技巧...

战双帕弥什新S冰露怎么玩呢&#xff0c;新的S构造体更新之后正式登场&#xff0c;不少玩家都对他不太了解&#xff0c;接下来就让小编给大家带来《战双帕弥什》新S冰露玩法技巧介绍。《战双帕弥什》新S冰露玩法技巧介绍 冰露技能分为两种形式&#xff0c;一种是极寒形态&#x…