Python入门学习笔记(八)——类和对象

Python学习(八)

目录

Python学习(八)

类和对象

面向对象编程

self是什么?

魔法方法

公有和私有

继承

多重继承

组合

类,类对象和实例对象

绑定

一些相关的BIF


类和对象

       对象 = 属性(变量,静态的) + 方法

       类:可以批量的生产对象

面向对象编程

Python是完全面向对象的语言,Object Oriented,具有以下特点:

  • 封装:也是信息隐蔽技术
  • 继承:子类继承父类
  • 多态:不同类的同名方法;子类对父类方法的重写

self是什么?

类似this

>>> 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()
我是足球,谁踢我。。。

魔法方法

_init_(self,param1,param2……)

类似构造方法。

重写这个方法实现初始化

>>> class Ball:
	def __init__(self,name):
		self.name=name
	def kick(self):
		print('我是%s,谁踢我。。。' % self.name)

		
>>> b=Ball('球')
>>> c=Ball()
Traceback (most recent call last):
  File "", line 1, in 
    c=Ball()
TypeError: __init__() missing 1 required positional argument: 'name'

抛异常:TypeError: __init__() missing 1 required positional argument: 'name'

如下图:

Python入门学习笔记(八)——类和对象_第1张图片

公有和私有

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

>>> class Person:
	__name = 'xiaomeili'
	def getName(self):
		return self.__name

	
>>> p=Person()
>>> p.__name #直接调用会抛出异常
Traceback (most recent call last):
  File "", line 1, in 
    p.__name
AttributeError: 'Person' object has no attribute '__name'
>>> p.getName()
'xiaomeili'

如下图:

Python入门学习笔记(八)——类和对象_第2张图片

实质上是:自动改写为_类名__变量名

>>> p._Person__name
'xiaomeili'

如下图:

所以Python的私有是伪私有,实质是没有权限控制的,可以被外部调用,只是调用的形式发生了变化。

 

继承

class DerivedClassName(BaseClassName)

子类->基类,父类或超类

定义一个父类:

>>> class Parent:
	def hello(self):
		print('父类')

 子类继承父类Person,便也有了hello方法:

>>> class Child(Parent):
	pass

>>> c=Child()
>>> c.hello()
父类

如下图:

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

import random as r
class Fish:
    def __init__(self):
        self.x = r.randint(0,10)
        self.y = r.randint(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

class Shark(Fish):
    def __init__(self):
        #这里重写了父类的init方法,不想父类方法被覆盖可以:调用未绑定的父类方法
        Fish.__init__(self)
        #或者使用super函数(推荐),如果多层继承,更方便。
        super
        self.hungry = True
    def eat(self):
        if self.hungry:
            print('haha')
            self.hungry = False
        else:
            print('吃饱了')

运行,调用:

>>> s = Shark()
>>> s.move()
我的位置 6 6
>>> s.hungry
True
>>> s.eat()
haha
>>> s.eat()
吃饱了

多重继承

>>> class C(Base1,Base2):

        pass

容易造成代码混乱,尽量避免使用

 

组合

把没有继承关系的几个类组合,在一个类中实现其他类的实例

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条!

类,类对象和实例对象

创建一个类C,a、b为类C的实例对象

>>> class C:
	count = 0

	
>>> a = C()
>>> b = C()
>>> a.count
0
>>> b.count
0
>>> a.count += 10
>>> a.count
10
>>> b.count
0

而类C本身是类,也是一个对象,Python中无处不对象

>>> C.count += 100
>>> C.count
100
>>> a.count
10
>>> b.count
100

之前给a实例对象中的属性赋值了,所以a.count没有变。 

总结:

  • 类定义:C
  • 类对象:C
  • 实例对象:a,b

注:

不要试图在一个类里边定义出所有能想到的特性和方法,应该利用继承和组合机制来进行扩展

用不同的词性命名,如属性名用名词,方法名用动词

>>> class C:
	def x(self):
		print("X-man!")

		
>>> c = C()
>>> c.x()
X-man!
>>> c.x = 1
>>> c.x
1
>>> c.x()
Traceback (most recent call last):
  File "", line 1, in 
    c.x()
TypeError: 'int' object is not callable

上述做法会抛出异常TypeError: 'int' object is not callable

Python入门学习笔记(八)——类和对象_第3张图片

绑定

Python严格要求方法需要有实例才能被调用,这种限制就是Python的绑定概念

创建一个类B

>>> class B:
	def printB():
		print("BBBBBBB")

用类对象直接调用

>>> B.printB()
BBBBBBB

然而,当把类实例化后,无法调用printB

>>> b = B()
>>> b.printB()

抛出异常TypeError: printB() takes 0 positional arguments but 1 was given

Python入门学习笔记(八)——类和对象_第4张图片

 

继续看,我们在创建一个类C:

>>> class C:
	def setXY(self,x,y):
		self.x = x
		self.y = y
	def printXY(self):
		print(self.x,self.y)

创建类C的实例d,用__dict__查看属性,返回空字典          

>>> d = C()
>>> d.__dict__
{}

直接用类对象调用,返回如下:

>>> C.__dict__
mappingproxy({'__module__': '__main__', 'setXY': , 'printXY': , '__dict__': , '__weakref__': , '__doc__': None})

调用setXY属性

>>> d.setXY(4,5)
>>> d.__dict__
{'x': 4, 'y': 5}

可以看到,实质上传入的是:d.setXY(d,4,5),所以这两个属性是只属于实例对象的, C.__dict__中没有,这也是self的作用

之后我们删除C

>>> del C
>>> e = c()
Traceback (most recent call last):
  File "", line 1, in 
    e = c()
TypeError: 'C' object is not callable

报错TypeError: 'C' object is not callable,不能建立C的实例对象了

但是之前创建的d实例对象仍然可以调用x,y属性

>>> d.printXY()
4 5

Python入门学习笔记(八)——类和对象_第5张图片

 

一些相关的BIF

issubclass(class,classinfo):检查一个类是否是另一个类的子类,是一种宽松的检查

  1. 一个类被认为是其自身的子类
  2. classinfo可以是类对象组成的元祖,只要class与其中任何一个候选类的子类,则返回True
>>> class A:
	pass

>>> class B(A):
	pass

>>> issubclass(B,A)
True
>>> issubclass(B,B)
True
>>> issubclass(B,object) #object是又有类的基类
True

isinstance(object,classinfo):检查一个实例对象是有属于一个类

  1. 如果第一个参数不是对象,则永远返回False
  2. 如果第二个参数不是类或者由类对象组陈的元组,会抛出一个TypeErrot异常

 

hasattr(object,name):检查一个对象是否有指定的属性

>>> class C:
	def __init__(self,x=0):
		self.x = x

>>> c = C()
>>> hasattr(c,'x')  #注意要用引号括起来
True

 

getattr(object,name[,default]):返回对象指定的属性值,如果不存在,可以配置默认人的返回值。

不指定的话,抛出异常AttributeError: 'C' object has no attribute 'y'

>>> getattr(c,'x')
0

>>> getattr(c,'y')
Traceback (most recent call last):
  File "", line 1, in 
    getattr(c,'y')
AttributeError: 'C' object has no attribute 'y'

>>> getattr(c,'y','不存在')
'不存在'

Python入门学习笔记(八)——类和对象_第6张图片

setattr(object,name,value):设置对象中指定属性的值,如果对象不存在,新建一个属性,并赋值

>>> getattr(c,'y','不存在')
'不存在'
>>> setattr(c,'y','新属性')
>>> getattr(c,'y')
'新属性'

delttr(object,name):用于删除对象中指定的属性,如果属性不存在,抛异常AttributeError: p

>>> delattr(c,'p')
Traceback (most recent call last):
  File "", line 1, in 
    delattr(c,'p')
AttributeError: p

Property(fget = None, fset = None, fdel = None, doc = None):通过属性设置属性,第一个参数是获取属性的方法,第二个参数是设置属性的方法,第三个参数是删除属性的方法。 

按照上述的属性创建类C:

>>> class C:
	def __init__(self,size = 10):
		self.size = size
	def getSize(self):
		return self.size
	def setSize(self,value):
		self.size = value
	def delSize(self):
		del self.size
	x = property(getSize,setSize,delSize)

之前要获取属性值,需要调用getSize(),现在只需x,删除x后,调用getSize()报错AttributeError: 'C' object has no attribute 'size'

>>> c = C()
>>> c.getSize()
10
>>> c.x
10
>>> c.x = 18
>>> c.x
18
>>> c.getSize()
18
>>> del c.x
>>> c.getSize()
Traceback (most recent call last):
  File "", line 1, in 
    c.getSize()
  File "", line 5, in getSize
    return self.size
AttributeError: 'C' object has no attribute 'size'

Python入门学习笔记(八)——类和对象_第7张图片

你可能感兴趣的:(Python)