也说python的类--基于python3.5
在面向对象的语言中,除了方法、对象,剩下的一大重点就是类了,从意义上来讲,类就是对具有相同行为对象的归纳。当一个或多个对象有相同属性、方法等共同特征的时候,我们就可以把它归纳到同一个类当中。在使用上来讲,类的存在,就是为了方便管理对象。python中定义一个类的代码如下:
- class Simple_class(object):
- #定义一个名为Simple_class的类,python3以后默认object做为类的基类,这里不讨论新式和旧式类的区别
- height = 1.58#定义一个类变量
- def __init__(self,name,age,):#重写类的初始化,
- #使其在初始化的时候需要传入name,age两个参数。self为类方法的默认参数
- self.name = name #定义两个对象变量
- self.age = age
- def Print_details(self):#定义一个名为Print_details的对象方法
- print("Print_details方法调用:name is %s,age is %d"%(self.name,self.age))
- print("未初始化访问类变量:height = ",Simple_class.height)# 访问类变量
- try:
- print(Simple_class.name) #访问实例变量 因为会报错,为了程序代码执行 给了一个异常处理
- except AttributeError as error:
- print("未初始化之前访问实例变量的异常信息:",error)
- obj = Simple_class("object",115) #生成一个类的实例对象
- obj.height = 1.88
- print("初始化之后赋值给实例的类变量 height = ",obj.height)
- print("初始化之后的原始类变量:height = ",Simple_class.height)
- print("初始化之后访问实例变量:name is ",obj.name)#访问实例变量
- obj.Print_details()#调用对象方法
- # /////输出结果如下 ///////
- /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/s10/day4/blog.py
- 未初始化访问类变量:height = 1.58
- 未初始化之前访问实例变量的异常信息: type object 'Simple_class' has no attribute 'name'
- 初始化之后赋值给实例的类变量 height = 1.88
- 初始化之后的原始类变量:height = 1.58
- 初始化之后访问实例变量:name is object
- Print_details方法调用:name is object,age is 115
以上,我们定义了一个类,类中包括一个重写的初始化方法,一个普通类方法。一个类变量,两个实例变量。从输出内容上我们来分析一下类变量和实例变量的区别,在实例化对象之前,是可以直接访问类变量并且取出赋值给别的变量,而实例变量则是在实例化之后,只能通过实例对象访问的变量,如果在有具体的实例对象之前直接通过类去访问,则程序会报错。这是二者的区别。从使用意义上来讲,个人认为,类变量更像是实例的默认变量,他是每一个实例对象带有的默认变量且有值,这个值在实例化对象之后可以进行修改,不影响其他实例对象。而实例变量则是各个实例的特有变量,必须要进行赋值之后才能使用。再说初始化方法和我们定义的方法,初始化方法属于类方法,可以直接调用。而对象方法需要通过实例调用。
在上一段代码中有一个关于基类的概念,实际上也就是继承。在编写代码的时候,我们想对一个类进行一些额外的扩充,而又不影响它本身的状态,那就可以写一个子类来满足,这里先从单重继承说起,代码如下:
- class father_class(object):
- #定义一个名为father_class的类,他既是子类的父类,又是子类的子类的基类
- name = "父类" #定义一个类变量
- def log(self):
- #定义一个log方法 输出类名,这里不用self.__class取,是为了在子类调用时self会指向子类自身,不方便日志分辨。
- print("father_class")
- def public_func(self):#定义一个public_func方法,输出此方法是否被子类修改过
- print("未修改")
- class son_class(father_class): #定义一个子类,直接继承父类
- son_name = "子类"#定义一个类变量
- def son_log(self): #定义自身的log
- print("son_class")
- def public_func(self):#修改父类提供的公共方法
- print("子类修改父类方法")
- class grandson_class(son_class):
- #定义一个名为grandson_class的类继承自son_class由于son_calss也是别人的子类
- #所以son_class的父类是本类的基类
- grandson_name = "子类的子类"
- def grandson_log(self):#定义自身log
- print("grandson_class")
- def public_func(self):#对基类方法进行修改
- print("子类修改基类方法")
- ########父类的实例对象##########
- father = father_class() #生成一个父类的实例对象
- name = father.name
- #获取类变量的值并打印,类变量本身不用实例化也可以获取,但下文需要实例调用方法,所以就先生成了
- print("父类访问自身类变量:",name)
- father.log()#父类调用自身的方法
- father.public_func()
- #######子类的实例对象###########
- son = son_class()#实例化一个子类对象
- name = son.name #子类去获取父类的类变量并这打印。输出结果无误,说明子类可以继承父类所有的类变量。
- #同理也可以继承父类所有实例变量,代码未举例,但原理一样
- print("子类访问父类变量:",name)
- son.log()#子类调用父类的方法,输出结果无误,说明子类可以继承父类所有的方法
- name = son.son_name#子类访问自身类变量的值并打印,结果无误,说明子类可以增加类变量
- print("子类访问自己的类变量:",name)#
- son.son_log()#子类调用自己的log方法,说明子类可以扩充自己的方法
- son.public_func()#子类调用父类的方法,但输出结果不同 ,因为我们在子类中进行过修改,说明子类可以修改父类方法
- #########子类的子类的实例对象
- grandson = grandson_class()#生成一个子类的子类的实例对象
- name = grandson.name#子类直接去访问父类的父类的类变量并打印,
- #结果无误,说明,我们除了继承父类的变量,还继承所有父类的父类,链条式。
- print("子类访问基类变量:",name)
- grandson.log()#子类调用父类的父类的方法,同理可得,子类也继承父类的父类的所有方法
- grandson.public_func()#子类可以直接修改父类的父类也就是基类的方法
- ########输出结果如下###############
- 父类访问自身类变量: 父类
- father_class
- 未修改
- 子类访问父类变量: 父类
- father_class
- 子类访问自己的类变量: 子类
- son_class
- 子类修改父类方法
- 子类访问基类变量: 父类
- father_class
- 子类修改基类方法
以上代码是一个简单的单继承概括,从代码中,可以看到,当一个类继承自另一个类,那么它将拥有父类的一切数据,包括父类变量,父类的实例变量,以及父类方法,这个方法包括类方法和实例方法。同时,子类的作用就是对父类的扩充,也就是说它可以对父类的所有数据增加、更改。python是一个多继承语言,有时候我们想同时拥有两个类的方法,那直接继承两个类就可以。简单构造代码如下:
- class A(object):
- def a(self):
- pass
- class B(object):
- def b(self):
- pass
- class C(A,B):
- pass
- c_test = C()
- c_test.a()
- c_test.b()
从上面代码中可以看出,C类继承自A,B两个类,所以它既可以调用A的方法,又可以调用B的方法。(ios只能通过协议实现。。差评!!!),多继承的特性和单继承差不多是一样的,但值得注意的是,多继承会涉及到方法重复。那么,这里衍生出一个问题。普通继承与super继承。首先来看一段代码:
- class A(object):#这么简单的代码。。我就不解释了
- def __init__(self):
- print("A")
- class B(object):
- def __init__(self):
- print("B")
- class C(A):
- def __init__(self):
- print("C")
- A.__init__(self)
- class D(A):
- def __init__(self):
- print("D")
- A.__init__(self)
- class E(B,C):
- def __init__(self):
- print("E")
- B.__init__(self)
- C.__init__(self)
- class F(D,E):
- def __init__(self):
- print("F")
- E.__init__(self)
- D.__init__(self)
- a = E()
- print("---------")
- b = F()
- ######看一下输出记录,为了省地儿,我合成了两行行########
- # 初始化E类得到的输出结果 E B C A
- #---------
- # 初始化F类得到的输出结果 F E B C A D A
分析一下上面的代码,A,B都直接继承于基类,分别有自己的初始化方法,在初始化的时候输出自己的类名。C,D皆继承自A,改写它们的初始化方法,使其在初始化的时候不仅输出自己类名,同时调用一下自己父类的初始化方法即同时输出自己的父类名.E,F两个类为多重继承。来查看一下初始化E类的结果,没有异常,它初始化了自己,也调用了父类的初始化方法,同时调用了父类的父类的初始化方法。再看一下F类的初始化结果。问题来了。它输出了两个A。由此可以分析出。它调用了两次A类的初始化方法,这是代码中极为不愿意看到的。让我们来分析一下代码,看这个问题是如何出现的。首先F继承自D,E两个类。而D继承自A,E继承自B,C。再往上分析,B继承自基类。而C继承自A。问题在这,每继承一个类,我们都对其进行了初始化方法调用。也就是说在F中我们调用了两次A的初始化方法,所以输出了两次。在实际运用中,我们也会遇到这个问题。那就是在多重继承中,常常由于类的关系复杂而使某些父类方法被其子类或者其子类的子类或者在子类重复调用。所以,我们要用到一个关键字super来解决这个问题,代码如下:
- class A(object):#代码都差不多。。这个也不解释了。。
- def __init__(self):
- print("A")
- super(A,self).__init__()
- class B(object):
- def __init__(self):
- print("B")
- super(B, self).__init__()
- class C(A):
- def __init__(self):
- print("C")
- super(C, self).__init__()
- class D(A):
- def __init__(self):
- print("D")
- super(D, self).__init__()
- class E(B,C):
- def __init__(self):
- print("E")
- super(E, self).__init__()
- class F(D,E):
- def __init__(self):
- print("F")
- super(F, self).__init__()
- a = E()
- print("---------")
- b = F()
- ######看一下输出记录,为了省地儿,我合成了两行行########
- # 初始化E类得到的输出结果 E B C A
- #---------
- # 初始化F类得到的输出结果 F D E B C A
如上,对比一下两份代码,不难看出super的作用,首先它自动查找父类的初始化方法并调用,同时保证只被调用一次,而且严格按照类继承路线走,关于最后一点可以对比一下两次代码的输出顺序,这个顺序涉及到python的多继承顺序算法,别管它了。除了初始化方法,对于其他方法,super也有同样的作用,需要注意的是,super只针对新式类。在单继承中,super大概被用于偷懒扩充父类构造方法。但是!混用super类和普通继承类比较危险,所以单继承个人很少使用。
以上,继承的问题基本谈完,最后说一下装饰器在类方法中的使用代码如下:
- class test(object):#定义一个类。。不要管名字了
- name = "test"#类变量
- def __init__(self,age):#初始方法,传个参数
- self.age = age#定义一个实例变量,把传进来的参数直接赋值给它
- def say(self):# 未加装饰器的普通方法,输出个test,ps:只能实例化之后通过实例调用
- print("test")
- @staticmethod#加装饰器@staticmethod之后的方法,
- #即静态方法 不无需实例化调用 ,无法传参数。当一个类只有静态方法的时候,从意义上讲就单纯是一个类的工具包
- def say2():
- print("say hi 2")
- @classmethod
- # 类方法 ,不需要实例化即可调用,可以使用类参数,无法使用实例参数,这里没有传个参数做例子。。抱歉
- def say3(self):
- print("say hi 3")。
- @property #加@property的方法
- #可以返回数据,使用意义上来讲,就是把经过类方法处理后的数据传递出去
- def say4(self):
- # print("this is 4")
- return "test"
以上是python中类的一些简单注意事项,做为面向对象的一大重点,类这一概念还有很多值得深究的东西。例如参数类型等等,这些都需要自己去慢慢探究。
也说python的类--基于python3.5的更多相关文章
- python基础知识——基于python3.6
语法糖 # # -*- coding: utf-8 -*- # #------------- # #--------- 语法糖--------------- # #------------------ ...
- Python基础-类
Python基础-类 @(Python)[python, python基础] 写在前面 如非特别说明,下文均基于Python3 摘要 本文重点讲述如何创建和使用Python类,绑定方法与非绑定方法的区 ...
- python基础系列教程——Python3.x标准模块库目录
python基础系列教程——Python3.x标准模块库目录 文本 string:通用字符串操作 re:正则表达式操作 difflib:差异计算工具 textwrap:文本填充 unicodedata ...
- python:类的基本特征------继承、多态与封装
一.继承 1,什么是继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 python中类的继承分为:单继承和多继承 cl ...
- Python菜鸟之路:Python基础-类(1)——概念
什么是类? 在python中,把具有相同属性和方法的对象归为一个类(class).类是对象的模板或蓝图,类是对象的抽象化,对象是类的实例化.类不代表具体的事物,而对象表示具体的事物. 类的创建 cla ...
- Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用
目录: 一.什么是Thrift? 1) Thrift内部框架一瞥 2) 支持的数据传输格式.数据传输方式和服务模型 3) Thrift IDL 二.Thrift的官方网站在哪里? 三.在哪里下载?需要 ...
- Sublime Text 2 (for OS X )配置成可以运行基于python3解释器的 .py文件
Mac自带的python 其version是python 2.7 官网下的Sublime Text 2部署好了以后默认也是 为了使ST2 可以在command+B时可以运行基于python3的.py, ...
- [python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)
星期一, 20. 八月 2018 01:53上午 - beautifulzzzz 1.前言 做类似zigbee.ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原 ...
- 基于Python3的漏洞检测工具 ( Python3 插件式框架 )
目录 Python3 漏洞检测工具 -- lance screenshot requirements 关键代码 usage documents Any advice or sugggestions P ...
随机推荐
- 【总结】使用WebBrowser遇到的陷阱
一.前言 一直想用WebBrowser做一些好玩的东西,比如抓取分析感兴趣的网站页面.自动点击提交页面等,所以最近在研究WebBrowser.WebBrowser的功能十分强大,就是一个微型的Brow ...
- PHP 进程间通信——消息队列(msg_queue)
PHP 进程间通信--消息队列 本文不涉及PHP基础库安装.详细安装说明,请参考官网,或期待后续博客分享. 1.消息队列函数准备 <?php//生成一个消息队列的key$msg_key = ft ...
- R语言获取数据类型信息的一些有用函数
向量.因子.时间序列x[i]: 矩阵.数据框x[i, j] x[i, ] x[, j]: 数组就是根据维度多打几个逗号而已x[i, j, k, -]: 列表要用双重中括号x[[i]]. 特殊的 ...
- RabbitMQ之window安装步骤
安装Rabbit MQ Rabbit MQ 是建立在强大的Erlang OTP平台上,因此安装Rabbit MQ的前提是安装Erlang.通过下面两个连接下载安装3.2.3 版本: 下载并安装 Era ...
- DHCP
安装 yum install -y dhcp 配置文件 默认配置为/etc/dhcpd.conf [root@samba ~]# [root@samba ~]# rpm -ql dhcp | grep ...
- c++ 接口和抽象类
其实对抽象类与接口的区别一直是搞不太清楚,最近正在学习<设计模式>,期间用到了很多c++多态的知识.这是才恍然发现,是应该整理下这方面的知识了.但在翻阅书本.上网查阅资料之际,发现有篇文章 ...
- C语言位域
转载自 http://tonybai.com/2013/05/21/talk-about-bitfield-in-c-again/ 再谈C语言位域 五 21 bigwhite技术志 bitfield, ...
- SEO之title优化
作者:andyrat,联系方式:andyrat@qq.com
- file_get_contents带bom
$dmText = file_get_contents( AROOT .'data' . DS . 'DMType.json.php'); if(preg_match('/^\xEF\xBB\xBF/ ...
- JS函数运行在它们被定义的作用域内,而不是它们被执行的作用域内
一个函数的作用域并不会因为被另一个函数调用而拓展,取得另一个函数的作用域: function show(name){ alert(name) } function show2(){ var name= ...