16.1 Python入门之类与对象

前言:

数据层面的封装是创建列表,代码层面的封装是创建函数,对象将数据和代码都封装了。


对象=属性+方法


对象的特征称为属性,行为称为方法


创建类


class Turtle:

   #Python的类名为大写字母开头

  color = 'green'

  legs = 4

def climb(self): #类的方法就是函数

  print('go')


以上代码定义对象的属性和行为,即创建了类。通过类创建对象,将类实例化,则创建出的对象称为类的一个实例,也称实例对象。


类的实例化示例


>>>tt = Turtle()


类的实例化过程类似于调用函数,所以要求类名大写字母开头,函数小写字母,易于区分。赋值操作即将创建好的实例对象赋值给一个变量,否则对象无法使用(没有任何引用指向该实例),会被当作垃圾回收。


调用对象的方法


使用点操作符即可


>>>tt.climb()

go


self


对象的方法都带有self参数,self相当于C++的this指针,self理解为能唯一标识类所创建的无数对象中某特定对象的存在。


Python的self同理,当某类实例化出无数对象时,调用其中某对象的方法,对象会将自身的引用作为第一个参数传入该方法,Python借此识别哪个对象的方法。


>>>class Ball:

   def setName(self,name):

      self.name = name

   def kick(self):

      print("you kick %s" % self.name)


>>>a = Ball()

>>>a.setName("me")

>>>b = Ball()

>>>b.setName("him")

>>>a.kick()

you kick me

>>>b.kick()

you kick him


构造函数


Python的特殊方法总是被双下划线包围,如_ _init_ _()方法,实例化对象时可以传入参数,这些参数自动传入_ _init_ _()方法中,达到初始化对象的目的。


该方法称为构造方法,会在类实例化一个对象时自动调用,利用此特性,使用该方法达到初始化对象的目的。


>>>class Potato:

   def _ _init_ _(self,name):

     self.name = name

   def kick(self):

     print("you kick %s" % self.name)

>>>p = Potato("potato")

>>>p.kick()

you kick potato


公有和私有


公有和私有用于控制访问权限,但Python并没有public和private关键字。默认对象的属性和方法都是公开的,通过点操作符进行访问。


>>>class Person:

   name = "Jack"


>>>p = Person()

>>>p.name

'Jack'


Python采用名字改编的方式来定义私有变量,即在变量或函数名前加上两个下划线"_ _"


>>>class Person:

   _ _name = "Jack"


>>>p = Person()

>>>p._ _name  #error


在外部将变量名隐藏起来,如果要访问,就需要从内部进行


>>>class Person:

    def _ _init_ _(self,name):

          self._ _name = name

    def getName(self):

          return self._ _name

>>>p = Person("Jack Ma")

>>>p._ _name  #error

>>>p.getName()

'Jack Ma'


仔细分析名字改编,其实Python只是把双下横线开头的变量进行改名,实际上等效于在外部使用"_类名_ _变量名"即可访问双下横线开头的私有变量


>>>p._Person_ _name

'Jack Ma'

(注:Python的私有机制是伪私有,类是没有权限控制的,所有变量都可被外部调用)


继承


语法

class 类名(被继承的类):


被继承的类称为基类,父类或超类,继承者称为子类,子类继承父类的任何属性和方法


>>>class Parent:

   def hello(self):

      print("haha")


>>>class Child(Parent):

     pass


>>>p = Parent()

>>>p.hello()

haha

>>>c = Child()

>>>c.hello()

haha


若子类定义与父类同名的方法属性,则会自动覆盖父类对应的方法或属性,包括构造方法:


>>>class Child(Parent):

     def hello(self):

       print("xixi")


>>>c = Child()

>>>c.hello()

xixi


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("my position:",self.x,self.y)


class Goldfish(Fish):

   pass


class Shark(Fish):

  def _ _init_ _(self):

    self.hungry = True

  def eat(self):

    if self.hungry:

       print("eat")

       self.hungry = False

    else:

      print("Too Much")


>>>fish = Fish()

>>>fish.move()

my positon:5 10

>>>goldfish = Fish()

my position:8 9

>>>goldfish.move()

my position:7 9

>>>goldfish.move()

my position:6 9

>>>shark = Shark()

>>>shark.eat()

eat

>>>shark.eat()

Too Much

>>>shark.move()   #error


虽然Shark继承了Fish,但其构造函数重写了父类的构造函数,而新的构造函数没有初始化x和y坐标,调用move()方法自然报错,所以重写构造方法时应先调用Fish类(基类)的构造函数,两种实现方法如下


调用未绑定的父类方法


class Shark(Fish):

  def _ _init_ _(self):

    Fish._ _init_ _(self)

    #该self是子类Shark的实例对象

    self.hungry = True


未绑定指的是不需要绑定父类的实例对象,而使用子类的实例对象代替


使用super函数


super()函数能自动找到父类的方法,并传入self参数


class Shark(Fish):

  def _ _init_ _(self):

    super()._ _init_ _()

    self.hungry = True


super在于不需要给出基类名字,自动找到基类及其对应方法,好处在于当改变基类时只要改变class语句中的父类即可,而不用在大量代码中修改所有被继承的方法


多重继承


不推荐使用


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


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



猜你喜欢

转载自blog.csdn.net/lwz45698752/article/details/78813537