python:14:类(1)-- 类的属性和方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/genome_denovo/article/details/79825728

第一章:python

第14节:类

1,类与对象,类的简单介绍

1)类表示一类实物的集合,类与实物的相互关系表示为,类是对象的定义,而实物存放了类中所定义的对象的信息。
2)面向对象编程的设计思路为:
····1> 确定对象的属性和方法
····2> 抽象具有共同特征的对象为一类
····3> 设计类和类之间的关系
····4> 实例化对象
3)类存在它的属性方法
属性(在类之外即为变量)表示对象的特征
方法(在类之外即为函数)表示对象的操作
4)如何创建一个类:
类的首字母要大写,而函数(或者是类当中的方法)的首字母要小写
class来定义一个类,写法为:
>>> class MyData(object): #MyData首字母大写,其他字母可以小写或大写
>>> ····pass
5)类即其中的属性和方法的一些事宜
类的命名要体现事物的过程及用途
属性命名要有数据值名字的特点
方法名应当指出对应对象或值的行为
6)类的实例化应用
比如下面的例子:
>>> class Car(object): #首字母大写定义一个类
>>> ····"""类的描述信息""" #类的描述信息
>>> ····color='black' #定义一个类的属性
>>> ····def run(self): #定义一个类的方法
>>> ········"""方法""" #方法的描述信息
>>> ········print 'go!' #方法的内容
>>>
>>> BMW=Car() #类的使用:创建一个类的对象实例,即类的实例化
>>> BMW.color='red' #访问类的属性,也可对类的属性进行重新赋值
>>> BMW.run() #访问类的方法
事项:在访问类的属性时不加括号,访问类的方法时加括号

2,类的属性

类存在三种属性:
1)公有属性(类被实例化后均可使用)。写法为:名字;例如:name=‘zhengzhou’
2)私有属性(类实例化后在外部无法访问,通常在类的内部,用于传值使用)。写法为:__名字(前面两个下划线加名字);例如:__number=10000
3)内置属性(或称为特殊属性)。写法为:__名字__(前后两个下划线加名字);例如:__str__
代码实例:
class Human(object):
····name='zhangsan'
····__money=800
zhangsan=Human
zhangsan.__money
Traceback (most recent call last):
··File "<stdin>", line 1, in <module>
AttributeError: type object 'Human' has no attribute '__money'
类实例化后其公有属性name可以访问,而私有属性__money不可以访问

3,决定类的属性

要知道一个类的所有属性,可通过两种方法:
1)利用内建函数dir()
2)访问类的字典属性__dict__
例如查看python自带的列表(list)的所有属性
>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
或者
>>> list.__dict__
dict_proxy({'__getslice__': <slot wrapper '__getslice__' of 'list' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'list' objects> ··· ··· })
二者区别在于dir()返回的仅仅是对象的属性的一个名字列表,而__dict__ 返回的是一个字典,它的键(key)是属性名,值(value)是相应的属性对象的数据值。

4,特殊的类属性

对于任何类C,其所有特殊属性如下:
表13.1
特殊类属性
| C.__name__ | 类C的名字(字符串) | #名字
| C.__doc__ | 类C的文档字符串 | #文档
| C.__bases__ | 类C的所有父类构成的元组 | #元组
| C.__dict__ | 类C的属性 | #属性
| C.__module__ | 类C定义所在的模块 | #模块
| C.__class__ | 实例C对应的类 | #实例
例如如下的类:
>>> class MyClass(object):
... ····'MyClass class definiton'
... ····myVersion = '1.1'
... ····def showMyVersion(self):
... ········print MyClass.MyVersion
... #例子当中定义了一个类,有类的描述信息,类的属性和方法
>>> MyClass.__name__ #返回的结果是给出类的字符名字,返回一个字符串
'MyClass'
>>> MyClass.__doc__ #返回的结果该类的描述信息,返回一个字符串
'MyClass class definiton' #__doc__ 是类的文档字符串,与函数及模块的文档字符串相似,但必须紧随头行(header line)后面的字符串。文档字符串不能被派生类继承,派生类必须含有它们自己的文档字符串。
>>> MyClass.__bases__ #返回所有父类构成的元组,当然该类没有父类,或者说父类只是object,如果是class MyClass(): 则返回一个空元组
(<type 'object'>,)
>>> print MyClass.__dict__ #返回一个字典,包含类的所有数据属性
{'__module__': '__main__', 'showMyVersion': <function showMyVersion at 0x7f235c972b90>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, 'myVersion': '1.1', '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': 'MyClass class definiton'}
>>> MyClass.__module__
'__main__'
>>> MyClass.__class__
<type 'type'>

4,类的方法

类的方法也分为两种:
1)公有方法,def funName(self): 该方法实例化后可以使用
2)私有方法,def __funName(self): 该方法实例化后外部不可以使用,仅在类的内部可以使用
例如:
>>> class Human:
... ····name='zhengzhou'
... ····__age=22
... ····def say(self): #定义公有方法,方法传入的第一个参数为self,self指代的是对象本身,即实例化对象
... ········print 'My name is %s I am %d years old'%(self.name, self.__age) #公有方法的内容,当然如果想在方法当中使用该类的类属性,则类属性在方法中被调用时需要加self,即self+.+属性名称,例如self.name和self.__age,类的私有方法在类实例化时无法直接访问,但可以通过调用类的方法来查看类的私有属性
... ····def __lie(self): #定义私有属性
... ········print 'I am 23'
...
>>> zhangsan=Human() #类的实例化
>>> zhangsan.say() #调用类的公有方法
My name is zhengzhou I am 22 years old #输出了两个类的属性的值,zhengzhou和22
>>> zhangsan.__lie() #在调用类的私有方法时会报错
Traceback (most recent call last):
··File "<stdin>", line 1, in <module>
AttributeError: Human instance has no attribute '__lie' #报错的信息内容

4,类的特殊方法,即__init__()“构造器”方法

__init__() 该方法叫做构造函数,其在类的实例化时自动被调用
其主要作用是,该方法实现对象的初始化作用,当类被实例化时,可以直接进行一些操作,主要用于类实例化后的外部接收传值
>>> class Human:
... ····def __init__(self, name, gender, age): #构造函数要接收4个传值,其中实例对象作为第一个参数(self)被传递给构造函数,另外name, gender, age表示实例化时的传值
... ········self.name=name
... ········self.gender=gender
... ········self.age=age
>>> zhangsan=Human('zhangsan', 'male', 30) #所以类Human在实例化时接受三个外部传值,并将外部传值赋给实例属性
>>> zhangsan.name #调用实例属性
'zhangsan'
>>> zhangsan.gender
'male'
>>> zhangsan.age
30
类在实例化时直接执行构造函数(__init__)当中的内容
>>> zhangsan=Human() #如果类在实例化时没有给构造函数(__init__)足够传参则会报错
Traceback (most recent call last):
··File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 4 arguments (1 given) #返回的报错信息

__init__() 应当返回None

如果定义了构造器,它不应当返回任何对象,因为实例对象是自动在实例化调用后返回的__init__() 就不应当返回任何对象(应当为None);如果返回非None的任何其他对象都会导致TypeError异常;
>>> class MyClass:
... ····def __init__(self):
... ········print 'initialized'
... ········return 1 #所以构造函数内不应该有return语句
...
>>> mc = MyClass()
initialized
Traceback (most recent call last):
··File "<stdin>", line 1, in <module>
TypeError: __init__() should return None

5,类属性、实例属性和类实例化时构造函数的传值的区别

类属性仅是与类相关的数据值,和实例属性不同,类属性和类是否实例化无关。这些值像静态成员那样被引用,即使在多次实例化中调用类,它们的值都保持不变。
访问类属性,可以用类名加属性名方法访问,也可以用实例化对象加属性名方法访问
1)类属性和实例属性
>>> class C(): #定义一个类C
... version = 1.2 #类属性version其值为1.2
...
>>> c = C() #类实例化
>>> C.version #通过类名加属性名访问类属性
1.2
>>> c.version #实例化对象加属性名访问类属性
1.2 #二者得到的结果相同
>>> C.version += 0.1 #通过类(只能这样)类更新类属性的值
>>> c.version
1.3
>>> C.version
1.3 #无论哪种方式都改变了类属性的值
>>> c.version += 0.1 #通过实例化对象更新值
>>> C.version #类属性的值没有变化
1.3
>>> c.version #而实例属性的值发生了变化
1.4000000000000001
类属性更新值改变类属性也改变实例化后的属性,实例属性更新值改变实例属性不改变类属性
1)类属性和类实例化时构造函数的传值
>>> class Human:
... ····name='ren'
... ····age=25
... ····def __init__(self, name, age):
... ········print "#"*50
... ········self.name=name #将外部传入name值赋给类当中name属性
... ········self.age=age #将外部传入age值赋给类当中age属性
...
>>> zhangsan=Human('zhangsan', 30) #Human这个类的实例化,及在初始化是对于__init__ 构造器的传值,name=’zhangsan’,age=30
##################################################
>>> zhangsan.name
'zhangsan'
>>> zhangsan.age
30 #通过实例化的传值,实例属性的值改变
>>> Human.name
'ren'
>>> Human.age
25 #而无论外部传值是什么,类属性的值永远不变
构造函数传值不改变类属性

6,属性的知识拓展

class MyClass:
····var1="类属性,也叫静态属性" #可以在对象当中访问,也可在类当中直接访问
····__var2="类的私有属性" #只能在类当中相互调用
····def __inti__(self):
········self.var2="var2是实例的属性" #将要实例化出对象的属性
········self.__var3="实例的私有属性" #对象的私有属性
········var4="简单变量,非属性,作用域只在该方法内" #局部变量,只在函数体当中起作用

7,构造器传值与类方法传值

1)如果方法在类实例化后,需要调用时需要传值,则在方法调用时也需要传值

>>> class Type:
... ····def __init__(self, zhengshu, zifuchuan):
... ········self.zhengshu=zhengshu
... ········self.zifuchuan=zifuchuan
... ····def show_number(self, zhengshu):
... ········print "shu chu %d"%self.zhengshu #注意这两处输出的都是Type这个类在实例化时的传值
... ····def show_str(self, zifuchuan):
... ········print "shu chu %s"%self.zifuchuan #注意这两处输出的都是Type这个类在实例化时的传值
>>> result=Type(20,'jieguo')
>>> result.show_number(30) #所以尽管在调用类的事例化方法时,传入的参数与实例化时的参数不同,但调用方法输入的结果仍然是实例化时传值的结果
shu chu 20
>>> result.show_number('90')
shu chu 20

2)如果想输入调用方法时的传值结果,则应该写成如下的格式

>>> class Type:
... ····def __init__(self, zhengshu, zifuchuan):
... ········self.zhengshu=zhengshu
... ········self.zifuchuan=zifuchuan
... ····def show_number(self, zhengshu):
... ········print "shu chu %d"%zhengshu #注意这两处的不同在于输出的结果是zhengshu而不是self.zhengshu,即输出外部传值而不是实例化时的传值
... ····def show_str(self, zifuchuan):
... ········print "shu chu %s"%zifuchuan #注意这两处的不同在于输出的结果是zifuchuan而不是self.zifuchuan,即输出外部传值而不是实例化时的传值
>>> result=Type(20,'jieguo') #实例化传值和上面相同
>>> result.show_number(30) #但这里在调用方法时的传值和实例化时的传值不同,输出的结果是调用方法时的传值;调用方法时传值30,实例化的传值是20
shu chu 30
>>> result.show_str('name') #这里的结果同上
shu chu name
>>> result.show_str() #当然传值数量不够也会报错
Traceback (most recent call last):
··File "<pyshell#15>", line 1, in <module>
····result.show_str()
TypeError: show_str() takes exactly 2 arguments (1 given)

扫描二维码关注公众号,回复: 3003459 查看本文章
3)如果想直接使用类当中的方法,可以不需要构造器

>>> class Type: #不需要构造器,直接加入方法
... ····def show_number(self, zhengshu):
... ········print "shu chu %d"%zhengshu
... ····def show_str(self, zifuchuan):
... ········print "shu chu %s"%zifuchuan
...
>>> result=Type()
>>> result.show_number(90)
shu chu 90
>>> result.show_number('10') #同时注意输入参数的类型,需要对应,否则会报错
Traceback (most recent call last):
··File "<pyshell#20>", line 1, in <module>
····result.show_number('10')
··File "<pyshell#17>", line 3, in show_number
····print "shu chu %d"%zhengshu
TypeError: %d format: a number is required, not str
>>> result.show_str('name')
shu chu name
总结类当中构造器的所用在于,将类实例化时传入的参数,变为实例化参数,而该实例化参数则能够应用到整个类当中;而在调用类的方法时的传值,该传值仅仅能够应用于该方法,不能够应用于类的其他方法,更不能成为类的实例化属性,除非通过一些特殊操作。

8,三个内置装饰器,或称为函数修饰符

1)staticmethod:类静态方法

作用:与成员方法的区别在于编写方法是不需要self参数,并且可以在类不进行实例化的情况下直接调用;
代码实例:
>>> class Human:
... ····name='ren'
... ····def __init__(self, name, age):
... ········self.name=name
... ········self.age=age
... ····@staticmethod #加入staticmethod这个函数修饰符
... ····def bye(): #既然加入了函数修饰符,则bye这个函数不需要self这个参数了,同时也将其变为一个静态方法
... ········print 'GAME OVER!'
...
>>> Human.bye() #所以在加入函数修饰符以后,可以直接用类访问staticmethod修饰过的方法
GAME OVER!
>>> tom=Human('name', 20) #如果用实例化方法访问,需要先对类进行实例化,并传参
>>> tom.bye() #之后再访问对象方法
GAME OVER!

2)classmethod:类方法

类方法与成员方法区别在于其所接收的第一个参数不是self,而是cls(当前类的具体类型);简单来讲,对于类方法而言,需要类作为第一个参数,而非self这个实例,它是由解释器传给方法。类不需要特别地命名,类似self,不过很多人使用cls作为变量名。
例如:
>>> @classmethod
>>> def say(cls): #当然括号当中写self也无所谓
... ····print 'my name is %s and I have %d'%(self.name, self.__money)
classmethod用法和staticmethod用法类似,但正常来说,方法中可以有self,而staticmethod是没有self的
这两种修饰器的特点是,加入之后类可以直接调用方法,而无需进行实例化

3)property:属性方法

属性方法的作用在于,其可将一个类方法转变成一个类属性,变为只读属性
先看一个没有属性方法的实例:
>>> class Human:
... ····name='ren'
... ····@classmethod
... ····def say(self):
... ········print 'my name is %s'%self.name
... ········return self.name #对于类方法做一个return
...
>>> tom=Human() #实例化,实例化时虽然不需要传参,但是在实例化时需要加括号
>>> x=Human.say() #将say方法中的return值交给x
my name is ren
>>> print x #打印出的结果是Human当中的属性name
ren
>>> tom.say() #调用实例化当中的say方法
my name is ren
'ren'
>>> tom.say #但是如果按照实例化属性的方式调用方法会出现下面结果
<bound method classobj.say of <class __main__.Human at 0x024EE9D0>>
如果加入@property这个属性方法,则可以将方法直接转变为属性
>>> class Human:
... ····name='ren'
... ····@classmethod
... ····def say(self):
... ········print 'my name is %s'%self.name
... ········return self.name
...
>>> jam=Human() #实例化方法同上
>>> jam.say #加入了属性方法,这时实例化后的say已经是一个类属性而非方法了
my name is ren
'ren'
>>> x=jam.say 可以将return值赋给一个变量
my name is ren
>>> x
'ren'

下面则简要说明property属性方法加入前后的区别
>>> class Person:
... ····def __init__(self, first_name, last_name):
... ········self.first_name=first_name
... ········self.last_name=last_name
... ····def full_name(self):
... ········return "%s %s"%(self.first_name, self.last_name)

>>> full=Person('hua','sheng')
>>> fullname=full.full_name()
>>> fullname
'hua sheng'
>>> full.full_name
<bound method Person.full_name of <__main__.Person instance at 0x02D214B8>>

>>> class Person:
... ····def __init__(self, first_name, last_name):
... ········self.first_name=first_name
... ········self.last_name=last_name
... ····@property
... ····def full_name(self):
... ········return "%s %s"%(self.first_name, self.last_name)

>>> full=Person('hua','sheng')
>>> fullname=full.full_name()
Traceback (most recent call last):
·File "<pyshell#82>", line 1, in <module>
··fullname=full.full_name()
TypeError: 'str' object is not callable
>>> full.full_name
'hua sheng'

猜你喜欢

转载自blog.csdn.net/genome_denovo/article/details/79825728