python类和对象入门_Python基础入门第十一章类和对象

11.2 对象 = 属性 + 方法

一个对象的特征称为"属性",一个对象的行为称为“方法”。

如果把乌龟写成代码,将会是下边这样:

#p11_1.py

class Turtle

: #特征的描述就是属性,在代码层面来看就是变量

#

python用class定义类,class是一个关键字,告诉系统我们要定义一个类

#class后面加一个空格然后加类名

#类名规则:首字母大写,如果多个单词用驼峰命名法

#若类名后面有小括号,则为继承

color =

'green'

weight =

10

legs =

4

shell =

True

mouth =

'大嘴'

#方法实际就是函数,通过调用这些函数来完成某些工作

def

climb(self) :

print('爬')

def

run(self) :

print('')

def

bite(self) :

print('')

def

eat(self) :

print('')

以上代码定义了对象的特征(属性)和行为(方法),但还不是一个完整的对象,将定义的

这些称为类。需要使用类来创建一个真正的对象,这个对象叫作这个类的一个实例(实例对象)

创建一个对象,也叫类的实例化:

>>>#先运行p11_1.py

>>>tt

=Turtle()

>>>

注意:类后面跟的小括号,这跟调用函数是一样的,所以在python中,类名约定用大写字母

开头,函数用小写字母开头,更容易区分。另外赋值操作并不是必须的,但如果没有把创建好

的实例对象赋值给一个变量,那这个对象就没办法使用。最终被python的垃圾收集机制收回。

那如果要调用对象里的方法,使用点操作符(.)即可

>>>tt.climb() 爬

>>>tt.bite()

>>>tt.eat()

11.3 面向对象编程

答案:self可以理解为一个字典变量,内部存的就是对象的数据属性。如: {'name':'zhang','age':'18'}就是这些。

注意只有数据属性,并没有创建新的类的方法。 类----->通过实例化生成----对象---->

(对象只是一串类似于字典的数据)

面向对象编程

通过一个例子稍微感受一下:

>>> class Ball :

def

setName(self , name) :

self.name

= name

def

kick(self)

print("我叫%s" % self.name)

>>> a = Ball()

>>> a.setName("飞行流火")

>>> b= Ball()

>>> b.setName("团队之星")

>>> c=

Ball()

>>> c.setName("土豆")

>>>a.kick()

我叫飞行流火

>>>b.kick()

我叫团队之星

>>>c.kick()

我叫土豆

class.py

a4c26d1e5885305701be709a3d33442f.png

1 class Box:

2 def __init__(self, boxname, size, color):

3 self.boxname = boxname

4 self.size = size

5 self.color = color #self就是用于存储对象属性的集合,就算没有属性self也是必备的

6

7 def open(self, myself):

8 print('-->用自己的myself,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))

9 print('-->用类自己的self,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))

10

11 def close(self):

12 print('-->关闭%s,谢谢' % self.boxname)

13

14

15 b = Box('魔盒', '14m', '红色')

16 b.close()

17 b.open(b) #本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。

18 print(b.__dict__) #这里返回的就是self本身,self存储属性,没有动作。

a4c26d1e5885305701be709a3d33442f.png

以上代码当中:

self 就是 对象/实例 属性的集合,

他们之间的关系如下:

1、Box是个类 ——》实例化——》b 对象/实例

2、Box类python中显示为: (接下一行)

——》实例化:b=Box('魔盒', '14m',

'红色') (接下一行)

——》得到对象/实例b,显示为<__main__.box object at>

0x00000233857AA518>

3、抽象体(接下一行)

——》实例的过程(接下一行)

——》得对对象,含有属性:{'boxname': '魔盒', 'size': '14m', 'color':

'红色'},即self。

self看似是一整个对象,实际上描述明白一个类就是生产对象的过程,描述了self就是得到了对象。所以self内的健值可以直接使用。

正如自然界中,一个有效的对象,必须包括:1、描述对象的属性;2、对象的方法。

所以self是必须的,也是对象中重要的特性。

当掌握了这个原理以后,我们试试以下的代码,感觉更加神奇。让我们明白重要的是它的思路:

class02.py

a4c26d1e5885305701be709a3d33442f.png

class Box:

def myInit(mySelf, boxname, size, color):

mySelf.boxname = boxname

mySelf.size = size

mySelf.color = color #自己写一个初始化函数,一样奏效,甚至不用self命名。其它函数当中用标准self

return mySelf #返回给实例化过程一个对象!神奇!并且含有对象属性/字典

#def __init__(self, boxname, size, color):

#self.boxname = boxname

#self.size = size

#self.color = color #注释掉原来标准的初始化

def open(self, myself):

print(self)

print('-->用自己的myself,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))

print('-->用类自己的self,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))

def close(self):

print('-->关闭%s,谢谢' % self.boxname)

#经过改造,运行结果和标准初始化没区别

b = Box().myInit('魔盒', '14m', '红色')

#b = Box('魔盒', '14m', '红色')#注释掉原来标准的初始化方法

b.close()

b.open(b) #本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。

print(b.__dict__) #这里返回的就是self本身,self存储属性,没有动作。

a4c26d1e5885305701be709a3d33442f.png

换个角度来讲,

对类的操作有:1、定义属性 2、调节方法的选项

——》在适当的设置以后《———

类对的反馈有:1、得到属性 2、执行方法

在类的函数当中,self为什么是必要参数,因为他是对象的载体,可以理解成一个字典。

通过以下代码演示:

a4c26d1e5885305701be709a3d33442f.png

1 class Box:

2 def myInit(mySelf, boxname, size, color):

3 print(mySelf.__dict__)#显示为{}空字典

4 mySelf.boxname = boxname

5 mySelf.__dict__['aa'] = 'w'#甚至可以像字典一样操作

6 mySelf.size = size

7 mySelf.color = color #自己写一个初始化函数,一样奏效,甚至不用self命名。其它函数当中用标准self

8 return mySelf #返回给实例化过程一个对象!神奇!并且含有对象属性/字典

9

10 #def __init__(self, boxname, size, color):

11 #self.boxname = boxname

12 #self.size = size

13 #self.color = color #注释掉原来标准的初始化

14

15 def open(self, myself):

16 print(self)

17 print('-->用自己的myself,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))

18 print('-->用类自己的self,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))

19

20 def close(self):

21 print('-->关闭%s,谢谢' % self.boxname)

22

23

24 #经过改造,运行结果和标准初始化没区别

25

26 b = Box().myInit('魔盒', '14m', '红色')

27 #b = Box('魔盒', '14m', '红色')#注释掉原来标准的初始化方法

28 b.close()

29 b.open(b) #本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。

30 print(b.__dict__) #这里返回的就是self本身,self存储属性,没有动作。

a4c26d1e5885305701be709a3d33442f.png

执行结果

a4c26d1e5885305701be709a3d33442f.png

{}

-->关闭魔盒,谢谢

<__main__.Box object at 0x0000026A2CBAA5F8>

-->用自己的myself,打开那个红色,14m的魔盒

-->用类自己的self,打开那个红色,14m的魔盒

{'boxname': '魔盒', 'aa': 'w', 'size': '14m', 'color': '红色'}

11.3.2 python的魔法方法

据说,Python

的对象天生拥有一些神奇的方法,它们总被双下划线所包围,他们是面向对象的

Python

的一切。他们是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些

方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的

行为,而这一切都是自动发生的。

python的这些具有魔法的方法,总是被双下划线包围。此处讲其中一个最基本的特殊方法:__init

__(),关于python的其他魔法方法,详见第十二章。

通常把__init()__方法称为构造方法,__init()__方法的魔力体现在只要实例化一个对象,这个方法

就会在对象被创建时自动调用,其实,实例化对象是可以传入参数的,这些参数会自动传入__init__()

方法中,可以通过重写这个方法来自定义对象的初始化操作。举个例子:

>>>class Potato :

def __init__(self, name)

self.name

= name

def kick(self) :

print("我叫%s,噢 谁踢我?!" % self.name)

>>>p = Potato("土豆") #实例化对象传入参数土豆,自动传入__init__()方法中

>>>p.kick()

我叫土豆,噢 谁踢我?!

11.3.3 共有和私有

一般面向对象的编程语言都会区分共有和私有的数据类型,像C++和Java它们使用public和private

关键字,用于声明数据是共有的还是私有的,但在python中没有类似的关键字来修饰。

默认对象的属性和方法都是公开的,可以直接通过点操作符(.)进行访问:

>>>class Person :

name = "小甲鱼"

>>>p = Person()

>>>p.name

'小甲鱼'

为了实现类似私有变量的特征,python内部采用了一种叫 name mangling(名字改编)的技术,

在python中定义私有变量只需要在变量名或函数名前加上“__”两个下划线,那么这个函数或变量

就会成为私有的了:

>>> class Person :

__name = '小甲鱼'

>>> p = person()

>>> p.__name

报错

这样在外部将变量名“隐藏”起来了,理论上如果需要访问,就需要从内部进行:

>>>class Person :

def __init__(self, name)

self.__name =

name

def getName(self)

:

return

self.__name

>>> p = Person('小甲鱼')

>>> p.__name

报错

>>> p.getName()

'小甲鱼 '

>>>

p._Person__name #实际上在外部使用__类名__变量名

即可访问双下横线

’小甲鱼‘ #的私有变量了

注意:python目前的私有机制其实是为私有,python的类是没有控制权限的,所有变量

都可以被外部调用。

11.4 继承

语法很简单:

class 类名(被继承的类):

>>>class Parent :

def

hello(self):

print("正在调用父类的方法")

>>>class Child(Parent) :

pass

>>>p = Parent()

>>>p.hello()

正在调用父类的方法

>>>c = Child()

>>>c.hello()

正在调用父类的方法

注意:如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性:

>>>class Child(Parent) :

def

hello(self):

print("正在调用子类的方法")

>>>c = Child()

>>>c.hello()

正在调用子类的方法

尝试写一下刚才提到的金鱼(Goldfish)、鲤鱼(Carp)、三文鱼(Salmon),还有鲨鱼(Shark)

# p11_2.py

import random as r

class Fish:

def __init__(self):

self.x = r.random(0,10)

self.y = r.random(0,10)

def move(self):

self.x -= 1

print("我的位置是:",self.x ,

self.y)

class Goldfish(Fish):

pass

class Carp(Fish):

pass

class Salmon(Fish):

pass

#上面几个都是食物,不需要有个性,所以直接继承Fish类的全部属性和方法即可

#下边定义鲨鱼类,这是个吃货,除了继承Fish类的属性和方法,还要添加一个吃的方法

class Shark(Fish) :

def

__init__(self):

self.hungry

= True

def

eat(self):

if

self.hungry :

print("吃货的梦想天天有的吃")

self.hungry = False

else:

print("太撑了,吃不下")

>>>shark = Shark()

>>>shark.move()

程序报错 Shark属性没有x属性

原因其实是这样的:在Shark类中,重写了魔法方法__init__,但新的__init__方法里边没有初始化

鲨鱼的x坐标和y的坐标,因此调用move方法就会出错

11.4.1 调用未绑定的父类方法

class Shark() :

def __init__(self):

Fish.__init__(self)

self.hungry = True

在运行发现鲨鱼可以移动了:

>>>#先运行修改后的p11_2.py

>>>shark = Shark()

>>>shark.move()

我的位置是:7 9

>>>shark.move()

我的位置是: 6 9

11.4.2 使用super函数

#将p11_2.py鲨鱼的代码作如下修改

class

Shark(Fish):

def __init__(self):

super().__init__()

self.hungry = True

>>>先运行修改后的p11_2.py

>>> shark = Shark()

>>> shark.move()

我的位置是: 6 1

>>> shark.move()

我的位置是: 5 1

super函数的超级之处在于你不需要明确给出任何基类的名字,它会自动帮你找出所有基类以及

对应的方法

11.5 多重继承

class

类名(父类1,父类2,...)

11.6 组合

在Python里其实很简单,直接把需要的类放进去实例化就可以了,这就叫组合:

#p11_3.py

class

Turtle:

def __init__(self, x):

self.num = x

class

Fish:

def __init__(self, x):

self.num = x

class

Pool:

def __init__(self,x,y):

self.turtle = Turtle(x)

self.fish = Fish(y)

def print_num(self):

print("水池里总共有乌龟%d只,小鱼%d条" %

(self.turtle.num , self.fish.num))

>>>pool = Pool(1,10)

>>>pool.print_num()

水池里总共有乌龟1只,小鱼10条

11.7 类、类对象和实例对象

>>>class C:

count = 0

>>> a = C()

>>> b = C()

>>> c = C()

>>> print(a.count, b.count,

c.count)

0 0 0

>>> c.count += 10

>>> print(a.count, b.count,

c.count)

0 0 10

>>>C.count += 100

>>>print(a.count, b.count,

c.count)

100 100 10

从上面例子可以看出,对实例对象c的count属性进行赋值后,就相当于覆盖了类对象C的count属性

如果没有赋值覆盖,那么引用的是类对象的count属性。

11.8 到底什么是绑定

>>>class BB :

def printBB() :

print("no zuo no die")

>>>BB.printBB()

no zuo no die

但这样做会有一个问题,根据类实例化后的对象根本无法调用里边的函数

>>>bb = BB()

>>>bb.printBB()

报错

实际上由于python的绑定机制,这里自动把bb对象作为第一个参数传入,所以才会出现typeerror

11.9 一些相关的BIF(内置函数)

1. issubcclass(class, classinfo)

如果第一个参数(class)是第二个参数(classinfo)的一个子类,则返回True,否则返回False

2. isinstance(object, classinfo)

如果第一个参数(object)是第二个参数(classinfo)的实例对象,则返回True,否则返回False

3. hasattr(object, name)

作用就是测试一个对象里是否有指定的属性

第一个参数是对象,第二个参数是属性名。

4. getattr (object, name[,default])

返回对象指定的属性值,如果指定的属性不存在,则返回default(可选参数的值);若没有设置

default参数,则抛出ArttributeError异常。

5. setattr(object, name, value)

与getattr对应,setattr()可以设置对象中指定属性的值,如果指定的属性不存在,则会新建属性并

赋值。

6. delattr(object, name)

与setattr()相反,delattr()用于删除对象中指定的属性,如果属性不存在则抛出错误

7. property(fget = None, fset = None, fdel =

None, doc = None)

property()是一个比较奇葩的BIF,它的作用是通过属性来设置属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值