《零基础入门学习Python》(37)--类和对象:面向对象编程相关知识

前言

前面我们了解一些关于面向对象编程的相关知识,下面我们来将有关self还有私有制和公有制的相关知识

知识点

  • self是什么——

python的self相当于C++的this指针。self相当于每个房间的门牌号,让每个人都能找到自己的房间。python的类就是同一个道理,由一个类可以生产很多个对象,这些类都长得很相似,因为他们都来自于同一个类的属性和方法。当一个对象的方法被调用的时候,对象会将自身作为第一个参数传给self参数,接收到self参数的时候,python就知道是哪一个对象在调用方法。

>>> class Ball:
	def setName(self,name):
		self.name = name
	def kick(self):
		print("我叫%s,该死的,谁踢我...."%self.name)

		
>>> 
>>> a=Ball()
>>> a.setName('球球')
>>> b = Ball()
>>> b.setName('IQ')
>>> c=Ball()
>>> c.setName('土豆')
>>> a.kick()
我叫球球,该死的,谁踢我....
>>> 
>>> c.kick()
我叫土豆,该死的,谁踢我....
>>> 
  • python的魔法方法——__init__(self) 

称其为构造方法,在实例化一个对象的时候,那么这个方法就会在对象被创建的时候自动调用。实例化对象的时候是可以串入参数的,这些参数会自动的进入这个方法。我们可以通过重写这个方法,来自定义对象的初始化操作。

>>> class Ball:
	def __init__(self,name):
		self.name = name
	def kick(self):
		print("我叫%s,该死的,谁踢我...."%self.name)

		
>>> b = Ball('土豆')
>>> b.kick()
我叫土豆,该死的,谁踢我....
  • 公有和私有

对象和方法都是公有的,可以通过(.)运算符来操作。

>>> class Person:
	name = 'baba'

	
>>> p = Person()
>>> p.name
'baba'

为了实现公有变私有的操作,python采用了一种叫name mangling技术—— 名字改编,名字重整。在python中定义私有变量只需要在变量名或函数名前加上"__"两个下划线,那么这个函数或者变量就会变为私有的了。同样上一个代码我们再变量name前面加上两个下划线,他就会出现以下错误,这就相当于在外面将name变量给隐藏起来了。

>>> class Person:
	__name = 'baba'

	
>>> 
>>> p=Person()
>>> p.name
Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    p.name
AttributeError: 'Person' object has no attribute 'name'

当然我们也可以通过其他的方法,在不影响name的私有制的前提下,我们来调用它通过方法再来使用它

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

	
>>> 
>>> p = Person()
>>> p.name
Traceback (most recent call last):
  File "<pyshell#44>", line 1, in <module>
    p.name
AttributeError: 'Person' object has no attribute 'name'
>>> p.getName()
'baba'

python这个技术其实就是讲双下划线的变量改变了一个名字

>>> p._Person__name#Person前面只有一个下划线
'baba'

测试题

0.以下代码体现了面向对象编程的什么特征?

答:体现了面向对象的多态特征

1.当程序员不想把同一段代码写几次,他们发明了函数,当程序员已经有一个类,而又想建造一个相似的类,他们会怎么办?

答:他们会定义一个新类基础已有的这个类,这样就只需要简单的添加和重写需要的方法即可。

2.self参数的作用是什么?

答:绑定方法,据说有了这个参数,python再也不会傻傻分不清哪个对象在调用方法了,你可以认为方法中的self其实是实例对象的唯一标准。

3.如果我们不希望对象的属性或方法被外部直接引用,我们可以怎么做?

答:我们可以在属性或者方法前面加上双下划线,这样从外部是无法直接访问到,会显示错误。(前面讲过了)

4.类在实例化后那个方法会被自动调用?

答:__init__方法会在类实例化时被自动调用,我们称为魔法方法。你可以重写这个方法,为对象定制初始化方案。

5.请解释下面代码错误的原因?

答:首先你要明白类、类对象、实例对象是三个不同的名词。

我们常说的类是指类定义,由于“python无处不对象”,所以当类定义之后,自然就是类对象。在这个时候,你可以对类的属性(变量)进行折旧访问(MyClass.name)

一个类可以实例化出无数的对象(实例对象),Python为了区分那个实例对象调用了方法,于是要求方法必须绑定(通过self参数)才能调用。而未实例化的类对象直接调用方法,因为缺少self参数,所以就会报错。 

动动手

0.按照以下要求定义一个游乐园的门票的类,并尝试计算2个成人+1个小孩的平日票价

class Ticket():
    def __init__(self,weekend=False,child=False):
        self.exp=100
        if weekend:
            self.inc = 1.2
        else:
            self.inc = 1

        if child:
            self.discount = 0.5
        else:
            self.discount = 1


    def calcPerice(self,num):
        return self.exp*self.inc*self.discount*num
======================== RESTART: D:/python/Ticket.py ========================
>>> 
>>> adult = Ticket()
>>> child = Ticket(child=True)
>>> print("2个成人+1个小孩平常票价:%.2f"%(adult.calcPerice(2)+child.calcPerice(1)))
2个成人+1个小孩平常票价:250.00

import random as r


legal_x = [0,10]
legal_y = [0,10]


class Turtle:
    def __init__(self):
        #初始体力
        self.power = 100
        #初始位置随机
        self.x = r.randint(legal_x[0],legal_x[1])
        self.y = r.randint(legal_y[0],legal_y[1])

    def move(self):
        #随机计算方向并移动到新的位置(x,y)
        new_x = self.x + r.choice([1,2,-1,-2])
        new_y = self.y + r.choice([1,2,-1,-2])
        
        #检查移动后是否超出场景x轴边界
        
        if new_x < legal_x[0]:
            self.x = legal_x[0] - (new_x-legal_x[0])
        elif new_x > legal_x[1]:
            self.x = legal_x[1] - (new_x-legal_x[1])
        else:
            self.x = new_x
        #检查移动后是否超出场景y轴边界

        if new_y < legal_y[0]:
            self.y = legal_y[0] - (new_y-legal_y[0])
        elif new_y > legal_y[1]:
            self.y = legal_y[1] - (new_y-legal_y[1])
        else:
            self.y = new_y

        #减少体力
        self.power -= 1

        #返回新的位置
        print('这条乌龟的位置x..==%d,y..==%d'%(self.x,self.y))
        return(self.x,self.y)

    def eat(self):
        self.power += 20
        if(self.power>100):
            self.power = 100

class Fish:
    
    def __init__(self):
        self.x = r.randint(legal_x[0],legal_x[1])
        self.y = r.randint(legal_y[0],legal_y[1])
        
    def move(self):
        #随机计算方向并移动到新的位置(x,y)
        new_x = self.x + r.choice([1,-1])
        new_y = self.y + r.choice([1,-1])
        
        #检查移动后是否超出场景x轴边界
        
        if new_x < legal_x[0]:
            self.x = legal_x[0] - (new_x-legal_x[0])
        elif new_x > legal_x[1]:
            self.x = legal_x[1] - (new_x-legal_x[1])
        else:
            self.x = new_x
        #检查移动后是否超出场景y轴边界

        if new_y < legal_y[0]:
            self.y = legal_y[0] - (new_y-legal_y[0])
        elif new_y > legal_y[1]:
            self.y = legal_y[1] - (new_y-legal_y[1])
        else:
            self.y = new_y


        #返回新的位置
        print('这条鱼的位置x..==%d,y..==%d'%(self.x,self.y))
        return(self.x,self.y)


turtle = Turtle()
fish = []
for i in range(10):
    new_fish = Fish()
    fish.append(new_fish)
    

print("一共:%d"%i)

while True:
    if not len(fish):
        print("鱼儿都被吃完了,游戏结束!")
        break

    if not turtle.power:
        print("乌龟体力耗尽,挂掉了!")
        break

    pos = turtle.move()
    for each_fish in fish[:]:
        if each_fish.move() == pos:
            #鱼儿被吃掉了
            turtle.eat()
            fish.remove(each_fish)
            print("有一条鱼被吃掉了.....")
        

猜你喜欢

转载自blog.csdn.net/qq_38721302/article/details/83510163