Python 类和实例

类是实例的模板,实例是依据类建立的对象。类和实例是面向对象编程最重要的两个概念。

根据同一个类建立的实例(或对象)具有相同的方法,但是他们各自可以有不同的数据。

类是对同一种事物的抽象(即一种事物所具有的相同部分),在 python 中使用关键字 class 来定义一个类,下面是一个最简单的类的定义

classPerson:

pass

以上代定义了一个空的类,该类不存在任何的属性和方法。从属于类的变量我们称之为类的属性,从属于类的函数我们称之为类的方法。

属性

属性有两种类型,从属于某一个类本身或从属于摸一个类的实例。从属于类的示例的我们称之为示例属性,从属于类本身的我们称之为类属性。

通过实例变量或 self 关键字可以给实例绑定属性

#!/usr/bin/env python3

# -*- coding:utf-8 -*-

classPerson:

def__init__(self,name):

self.name=name

person=Person('Bob')

person.age=31

print(person.name)

print(person.age)

print(Person.name)

print(Person.age)

以上代码执行结果如下

Bob

31

Traceback (most recent call last):

File"class.py", line13,in

print(Person.name)

AttributeError: type object'Person'has no attribute'name'

以上代码使用实例 person 和 self 分别定义了属性 age 和 name,在访问属性时通过实例 person 可正常获取 age 和 name 的值,但是当使用类 Person 来访问属性 age 和 name 是 python 提示type object 'Person' has no attribute 'name',即类 Person 不存在属性 name。

如果类 Person本身需要一个属性,可以直接在类中定义,它属于 Person 类本身,所有通过 Person 实例化的示例均可访问该属性。

#!/usr/bin/env python3

# -*- coding:utf-8 -*-

classPerson:

name='Person'

def__init__(self,age):

self.age=age

person1=Person(23)

person2=Person(33)

print(Person.name)

print(person1.name)

print(person1.age)

print(person2.name)

print(person2.age)

以上代码执行结果如下

Person

Person

23

Person

33

通过以上代码可以看出属性 name 直接在类中进行定义,不仅类 Person 可访问该属性,Person 的实例 person1 和 person2 同样可以访问该属性。

示例属性仅在该示例内可以使用。类属性不仅类可使用,通过该类实例化的实例同样可使用。

既然类的属性在类的实例中可使用,那么实例属性和类属性相同此时会发生什么呢,让我们来看以下代码。

#!/usr/bin/env python3

# -*- coding:utf-8 -*-

classPerson:

name='Person'

def__init__(self,name,age):

self.name=name

self.age=age

person=Person('Bob',33)

print(person.name)

print(person.age)

print(Person.name)

以上代码运行结果如下

Bob

33

Person

通过以上代码可以看出,当类属性和实例属性相同时,实例属性并不会覆盖类属性的值,通过实例访问时获取的是实例属性,通过类访问时获取到的是类属性。

在编写代码时要尽量避免出现类属性和实例属性相同的情况,因为此时实例属性会覆盖类属性,可能会得到与预期不同的结果。

在以上我们看到的代码中类或示例的属性对所有人都是可见,事实上使用类的初衷是隐藏内部的数据,通过方法来操作数据,从目前来说这与我们的初衷相悖。那么如果要隐藏内部属性该怎么做呢?我们可以在属性的名称前加上两个下划线,在 Python 中,实例的变量名如果以 __ 开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。我们将以上代码修改如下:

#!/usr/bin/env python3

# -*- coding:utf-8 -*-

classPerson:

def__init__(self,name,age):

self.__name=name

self.__age=age

defprint_age():

print("%s age is %s"%(self.name,self.age))

person=Person('Bob',33)

person.print_age()

print(person.__age)

以上代码运行结果如下

Bob age is33

Traceback (most recent call last):

File"", line14,in

AttributeError:'Person'object has no attribute'__age'

如上所示类的属性不能直接访问,这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。但是如果想要获取或修改内部属性改怎么处理,我们可以通过增加 get 和 set 方法来实现。

#!/usr/bin/env python3

# -*- coding:utf-8 -*-

classPerson:

def__init__(self,name,age):

self.__name=name

self.__age=age

defprint_age():

print("%s age is %s"%(self.name,self.age))

defget_name():

returnself.__name

defget_age():

returnself.__age

defset_name(name):

self.__name=name

defset_age(age):

self.__age=age

person=Person('Bob',33)

person.print_age()

print(person,get_age())

person.set_age(34)

print(person,get_age())

以上代码运行结果如下

Bob age is33

33

34

方法

类的方法既类中的函数,和普通函数不同的是类的方法第一个参数是 self,但是在调用该方法时不需要传入 self。除此之外,类的方法和普通函数没有什么区别,因此你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。

方法中的 self 是必须的,即使没有其它参数也必须有 self 参数。

在前面的代码中总是看到__init__ 方法,__init__ 方法是类的一个特殊方法,它有一个名字叫初始化函数,它在类被实例化时立即运行,它可以对任何你需要操作的目标对象进行初始化操作。就像前面的示例中所使用的,你不必显式调用该函数,在类的实例化过程中 python 会自动调用该函数。

需要注意的是在__init__ 方法前后分别有两个下划线。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181228G06SIF00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券