博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简述Python中的类与对象
阅读量:6689 次
发布时间:2019-06-25

本文共 7158 字,大约阅读时间需要 23 分钟。

Python中的类

类的定义

示例:

class Person:    country = "China"    def __init__(self, name, age):        self.name = name        self.age = age    def speak(self, word):        print(word)

其中 country 是类属性,即 Person类 的静态属性,speak() 为 Person类的函数属性,即类的动态属性~

类的实例化

对上述示例的类进行实例化:

>>> p = Person('Kitty', 18)       # 实例化 Person类,得到对象 p>>> p.name                              # 调用对象 p 的name属性'Kitty' >>> p.speak('hello')                 # 调用对象 p 的绑定方法hello

 

类中的 __init__ 方法用于初始化对象,而在类的是实例化过程中,对应类中第一个被调用的并不是 __init__ 方法,第一个被调用的是 __new__方法。在对象的初始化之前首先要创建对象,__new__方法正是用来创建这个对象~
 
类的实例化过程也可以通过如下语句来实现:

>>> p = object.__new__(Person)        # __new__方法继承自 object类>>> Person.__init__(p, 'Kitty', 18)>>> p.name'Kitty'

在Person类中重写 __new__方法:

class Person:    country = "China"    def __new__(cls, name, age):        print('__new__ called')        return super(Person, cls).__new__(cls)    def __init__(self, name, age):        self.name = name        self.age = age    def speak(self, word):        print(word)p = Person('Kitty', 18)          # 实例化对象print('name : %s' % p.name)# 输出结果:__new__ calledname : Kitty

很明显 __new__方法 是先于 __init__ 方法被调用的~

类的实例化过程大致步骤如下:
1、p = Person('Kitty', 18) ,会调用 Person类的__new__方法,并传递 name 和 age 参数
2、__new__方法 会创建一个 Person类的对象并返回
3、最后利用这个对象调用类的 __init__ 方法 完成初始化,__init__ 方法的第一个参数是self,对象在调用 __init__ 方法时会将自己当做参数传递给 这个self。
 
注意:__init__方法没有返回值~,__init__ 方法仅完成对象的初始化工作~
 

self是什么?

在类的内部,self 就是一个对象。使用对象调用方法时(对象的绑定方法),当前对象会被自动传递给 self,即 self 表示调用该方法的对象~

类属性的调用

操作类的变量属性:

>>> Person.country                  # 调用类属性'China'>>> Person.country = 'USA'     # 修改类属性>>> Person.country'USA'>>> del Person.country           # 删除类属性>>> Person.country                 # 删除后无法再调用Traceback (most recent call last):  File "
", line 1, in
AttributeError: type object 'Person' has no attribute 'country'

 

调用类的函数属性:
这里仅介绍绑定方法的调用(即第一个参数是self的方法),类中的其他方法暂先不做介绍~
 
speak() 是类的函数属性,对象调用不需要传递 self参数(对象调用 会自动完成self参数传值,下面会介绍),若是类来调用,则需要手动传递这个 self参数,即需要传递一个Person类的对象~

class Person:    country = "China"    def __init__(self, name, age):        self.name = name        self.age = age    def speak(self, word):        print(word)p = Person('Kitty', 18) p.speak('hello')                  # 对象调用,会自动将 对象p 作为第一个参数传递给 selfPerson.speak(p, '你好')     # 类调用需要手动传递 self 的值# 输出结果:hello你好

类的名称空间

类名.__dict__ 用来查看一个类(或对象)的名称空间,可以这样理解。其实__dict__是类的一个内置属性,存储所有实例共享的变量和函数(类属性,方法等),类的__dict__并不包含其父类的属性。对象中的 __dict__ 属性下面会介绍~

 
这里注意和 dir() 方法的区别,dir(类名或对象名) 会返回一个类(或对象)的所有属性,包括从父类中继承的属性。

Person类的__dict__属性{'__module__': '__main__',        # 所处模块'__init__': 
, # __init__方法'speak':
, # speak 方法'__dict__':
, # 应该就是指 类的__dict__属性,具体参阅:https://blog.csdn.net/lis_12/article/details/53519060'__weakref__':
, '__doc__': None} # # class说明文档

 

调用类的属性,首先会去类的名称空间中(Person.__dict__)寻找对应名称的key,相当于Person.__dict__['country'],也可以直接这样调用:

>>> Person.__dict__['country']'China'>>> Person.__dict__['country'] = 'USA'Traceback (most recent call last):  File "
", line 1, in
TypeError: 'mappingproxy' object does not support item assignment

 

注意:
__dict__ 对于类中的属性只能查看,不能修改~

Python内置属性

除了 __dict__,Python中的类还有很多别的内置属性:

__doc__ :类的说明
__name__: 类名
__module__: 类定义所在的模块
__bases__ : 包含了类的所有父类 的元组
 
示例如下:

class Person:    '''human being'''    country = "China"    def __init__(self, name, age):        self.name = name        self.age = age    def speak(self, word):        print(word)print(Person.__doc__)print(Person.__name__)print(Person.__module__)print(Person.__bases__)#结果输出:human beingPerson__main__(
,)

Python中的对象

对象的名称空间

class Person:    country = "China"    def __init__(self, name, age):        self.name = name        self.age = age    def speak(self, word):        print(word)

实例化一个Person类的对象 的过程中,init方法会将参数赋值给 name 与 age 属性,可以通过 实例的__dict__ 查看,注意:实例的__dict__ 仅存储与该实例相关的实例属性,没有函数属性,也没有共有属性~

>>> p = Person('Kitty', 18)>>> print(p.__dict__){'name': 'Kitty', 'age': 18}

 

注意 实例.__dict__ 与 类.__dict__ 的区别~
 
通过 类.__dict__ 可以查看类中的属性,但是不能修改,但是通过 实例.__dict__ 除了查看,还可以进行修改~

>>> p.__dict__['name']'Kitty'>>> p.__dict__['age']18>>> p.__dict__['name'] = 'abc'>>> p.__dict__['age'] = 20>>> p.name'abc'>>> p.age 20

对象的变量属性调用

通过对象可以直接调用该对象的变量属性,例如 p对象 的 name属性 和 age属性~

>>> p = Person('Kitty', 18)>>> p.name'Kitty'>>> p.age18

也可以通过 p对象 调用对应类(这里是Person类)的变量属性,若是类的变量属性发生变化,则所有对象获取到的类变量属性都会改变~

>>> p.country'China'>>> Person.country = 'UK'       # 修改 类的变量属性>>> p2 = Person('baby', 22)>>> p.country'UK'>>> p2.country'UK'

Tip:

  • 可以将所有类共有的属性设置成类属性;
  • 对象寻找属性会先在自己的名称空间中寻找,若是没有再去类的名称空间中寻找~

注意1

在修改类的变量属性时,若变量是不可变类型,则仅能通过 类名.变量属性 来修改,如下示例:

>>> Person.country = 'USA'     # 修改类属性>>> p.country   'USA'>>> p.country = 'UK'>>> p.country'UK'>>> Person.country'USA'>>> p2.country'USA'

p.country 并没有修改类属性,而是给自己添加了一个新的属性,这个新添加的属性存放在对象自己的名称空间中,类的变量属性 country 并没有发生改变~

>>> p.__dict__{'country': 'UK', 'age': 20, 'name': 'abc'}

 

在类中 self 表示当前调用的对象,当 self 引用的变量和类变量同名的时候,需要注意区分:这两个变量之间没有关联,self 引用的变量属于对象,放在对象的名称空间中,类变量则放在类名称空间中

class Person:    country = "China"    def __init__(self, name, age):        self.name = name        self.age = age        self.country = 'AUS'     # 添加对象属性    def speak(self):        print(self.country)############>>> p = Person('Kitty', 18)>>> p.country'AUS'>>> p.speak()AUS>>> Person.country'China'

注意2

当类变量为可变类型时,需要区分对象的 2种 操作:

class Person:    country = "China"    lst = []    def __init__(self, name, age):        self.name = name        self.age = age        self.lst.append(name)    def speak(self):        print(self.name)############>>> p = Person('Kitty', 18)>>> p.__dict__{'age': 18, 'name': 'Kitty'}>>> Person.lst['Kitty']

上述示例中,self 针对 lst 变量并不是一个赋值操作,而是调用了 lst的append方法,所以这个过程会先在对象的名称空间中寻找 lst 属性,对象的名称空间中没有,然后再去类的名称空间中寻找,Person类中存在该属性,于是调用其 append 方法。

 
这个过程通过对象修改了类的可变类型的变量~
 
若 self 针对 lst 变量是一个赋值操作,这样就为当前对象新增了一个 lst 属性

class Person:    country = "China"    lst = []    def __init__(self, name, age):        self.name = name        self.age = age        self.lst = name    def speak(self):        print(self.name)############>>> p = Person('Kitty', 18)>>> p.__dict__{'age': 18, 'name': 'Kitty', 'lst': 'Kitty'}>>> Person.__dict__{'__module__': '__main__', 'country': 'China', 'lst': [], '__doc__': None, '__init__': 
, 'speak':
}

对象的方法(绑定方法)

class Person:    country = "China"    def __init__(self, name, age):        self.name = name        self.age = age    def speak(self):        print(self.name + ', ' + str(self.age))############>>> p1 = Person('Kitty', 18)>>> p2 = Person('baby', 22)>>> p1.__dict__{'age': 18, 'name': 'Kitty'}>>> p2.__dict__{'age': 22, 'name': 'baby'}

可以看到对象的名称空间中没有函数属性,函数属性在类的名称空间当中

 

>>> Person.speak
>>> p1.speak
>>>> p2.speak
>

p1 和 p2 的 speak 方法为绑定方法(bound method),且 p1 和 p2 的 speak 方法内存地址不一致,这两个对象的 speak 方法都执行 类中对应的方法。

 
绑定方法,有两种:绑定到类的方法和绑定到对象的方法,上述示例中的方法为后者,绑定到对象的方法为对象专门定制,使用对象调用的时候,会自动将 当前对象传递给方法的第一个参数(self,一般都叫self,也可以写成别的名称),若使用类调用,则第一个参数需要手动传值~

>>> p1.speak()Kitty, 18>>> p2.speak()baby, 22>>> Person.speak(p1)     # 通过类调用Kitty, 18

这里仅对绑定到对象的方法做简单介绍,类中还有绑定到类的方法,还有非绑定方法等...,之后会介绍

.................^_^

转载于:https://blog.51cto.com/ljbaby/2341332

你可能感兴趣的文章
posix消息队列(1)
查看>>
using for jekyll
查看>>
Jenkins的授权和访问控制
查看>>
C/C++里的const(1)
查看>>
Expert 诊断优化系列-------------针对重点语句调索引
查看>>
解决Run As -> Java Application不能运行问题
查看>>
JSP 注释的详解及简单实例
查看>>
c:\Windows\System32\drivers\etc\hosts的作用
查看>>
2.Xml与多个对象的映射(聚合或组合)及注意事项
查看>>
java报表开发之报表总述
查看>>
正确释放Vector的内存
查看>>
【零基础学习iOS开发】【02-C语言】04-常量、变量
查看>>
最小堆的基础操作(Java)
查看>>
bzoj2039: [2009国家集训队]employ人员雇佣(最小割)
查看>>
AspNetCore Mvc 使用 PartialView
查看>>
bzoj1227: [SDOI2009]虔诚的墓主人(树状数组,组合数)
查看>>
Sql Server 网络配置
查看>>
Oracle案例11——Oracle表空间数据库文件收缩
查看>>
看博客学学Android(十四)
查看>>
在Windows下安装配置jforum测试环境
查看>>