python笔记task07:类与对象、魔法方法

十三、类与对象

1.对象 = 属性+方法

(1)类的定义及调用

对象是类的实例。

面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

类的组成由属性和方法组成

类的内部可以定义属性和方法,类的外部则可以直接调用属性或方法来操作数据。

类主要定义对象的结构,然后以类为模板创建对象。类不但包含方法定义,而且还包含所有实例共享的数据。

  • 封装:信息隐蔽技术

用关键字 class 定义 Python 类,关键字后面紧跟类的名称、分号和类的实现。

分号是啥??

【例子:】
定义一个类Turtle:

class Turtle: #类名第一个字母大写,turtle是龟的意思
    # 属性
    color = 'green'
    weight = 10
    legs = 4
    shell = True  #shell  壳
    mouth = '大嘴'
    
    #方法
    def climb(self):    #这里的self是啥
        print('我正在很努力的向前爬...')
    def run(self):
        print('我正在飞快的向前跑...')
    def bite(self):
        print('咬死你咬死你!!')
    def eat(self):
        print('有得吃,真满足...')
    def sleep(self):
        print('困了,睡了,晚安,zzz')
tt = Turtle()
print(tt)
# <__main__.Turtle object at 0x0000007C32D67F98>
print(type(tt))
# <class '__main__.Turtle'>

print(tt.__class__)
# <class '__main__.Turtle'>

输出tt的类名:

print(tt.__class__.__name__)
# Turtle

调用类中的方法:

tt.climb()
# 我正在很努力的向前爬...

tt.run()
# 我正在飞快的向前跑...

tt.bite()
# 咬死你咬死你!!

python的类也是对象,(前面说过对象是类的实例),它们是type类的实例。
比如int就是type的实例。

print(type(Turtle))
# <class 'type'>

关于上面用到的__class__,name
可以参考:

(a)python的常用内建方法

参考:Python常用内建方法:init,new,__class__的使用详解

(2)关于继承

类名一般是大写开头的单词,比如Turtle代表Turtle类。紧接着是(object),表示该类是从哪个类继承下来的。如果没有合适的继承类,就用object类。
【例子:】

class Turtle(object):
    pass
  • 继承:子类自动共享父类之间数据和方法的机制

【例子:】定义一个Mylist类,从父类list继承。

class MyList(list):
    pass
lst = MyList([1, 5, 2, 7, 8])
lst.append(9)
lst.sort()
print(lst)

# [1, 2, 5, 7, 8, 9]
[1, 2, 5, 7, 8, 9, 1, 2, 3]

由此可见Mylist自动共享了父类list的方法。

(3)多态

  • 多态:不同对象对同一方法响应不同的行动

【例子】

class Animal:
    def run(self):
        raise AttributeError('子类必须实现这个方法')
"""我们可以使用raise语句自己触发异常"""

class People(Animal):
    def run(self):
        print('人正在走')

class Pig(Animal):
    def run(self):
        print('pig is walking')
        
class Dog(Animal):
    def run(self):
        print('dog is running')

def func(animal):
    animal.run()

"""下面调用试试"""
func(Pig())
# pig is walking
func(Animal())
#AttributeError: 子类必须实现这个方法

这说明不同的对象对同一个方法.run()响应了不同的行动。
这里都涉及到了self,但是self是什么?

2.self

python的self相当于C++的this指针。
什么是this指针?

在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this
指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。

参考:读懂python中的self

【例子】

class Test:
    def prt(self):
        print(self)
        print(self.__class__)

t = Test()
t.prt()
# <__main__.Test object at 0x000000BC5A351208>
# <class '__main__.Test'>

和下面这个有什么区别?

Test.prt(1)
#1
#<class 'int'>

类的方法与普通的函数只有一个特别的区别 —— 它们必须有一个额外的第一个参数名称(对应于该实例,即该对象本身),按照惯例它的名称是 self。在调用方法时,我们无需明确提供与参数 self 相对应的参数
【例子】

class Ball:
    def setName(self, name):
        self.name = name

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

self.name = name这句话有什么用?
self.name=name这句话就是把外部传来的参数name值赋值给Ball类内自己的变量name。如下:


a = Ball()
a.setName("球A")
b = Ball()
b.setName("球B")
c = Ball()
c.setName("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我...

如上面的例子,通过setName这个方法(self.name = name)把外部的参数“球A”传给了Ball类内自己的变量name.

3.python的魔法方法

  • 据说,Python 的对象天生拥有一些神奇的方法,它们是面向对象的 Python 的一切…
  • 它们是可以给你的类增加魔力的特殊方法…
  • 如果你的对象实现了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,而这一切都是自动发生的…
  • 类有一个名为__init__(self[, param1, param2...])的魔法方法,该方法在类实例化时会自动调用。

还记得上面定义的类Ball吗,没有用魔法方法的时候,实例化需要调用方法setName:

a = Ball()
a.setName("球A")

但是现在已经使用了魔法方法__init__,所以我们只需要

class Ball:
    def __init__(self, name):
        self.name = name

    def kick(self):
        print("我叫%s,该死的,谁踢我..." % self.name)
a = Ball("球A")   #注意这里的区别
b = Ball("球B")
c = Ball("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我...

【例子】

class Turtle:
    def __init__(self, x):
        self.num = x  
        #这样的话传入的是乌龟的数量,调用的时候Turtle(3)就行,代表3只乌龟
    def speak(self):
        print("我们%d只乌龟在赛跑" % self.num)
 Turtle(2).speak()    #我们2只乌龟在赛跑

实例也是可以调用类方法吗?

4.公有与私有(待完善)

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

5.继承

这里还没有看懂

6.组合

首先定义三个类,乌龟、🐟、水池,用到了魔法方法:

class Turtle:
    def __init__(self, x):
        self.num = x  
        #这样的话传入的是乌龟的数量,调用的时候Turtle(3)就行,代表3只乌龟
        #这里只是定义了一种方法来传入乌龟的数量,并没有实际的“动作”

class Fish:
    def __init__(self, x):
        self.num = x


class Pool:
    def __init__(self, x, y):     #这里的self是说泳池自己
        self.turtle = Turtle(x)
        self.fish = Fish(y)

    def print_num(self):
        print("水池里面有乌龟%s只,小鱼%s条" % (self.turtle.num, self.fish.num))

上面的x,y和乌龟speak里的x一样,都是在调用时需要传入的参数。

p = Pool(2, 3)
p.print_num()
# 水池里面有乌龟2只,小鱼3条

练习题

1、以下类定义中哪些是类属性,哪些是实例属性?


class C:
    num = 0
    def __init__(self):
        self.x = 4
        self.y = 5
        C.count = 6

【答】.count是类属性
.x,.y是实例属性

2、怎么定义私有⽅法?
【答】在方法名前加上英文双下划线:__

3、尝试执行以下代码,并解释错误原因:

class C:
def myFun():
print(‘Hello!’)
c = C()
c.myFun()

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

要求:

  • 平日票价100元
  • 周末票价为平日的120%
  • 儿童票半价

【答】

class Ticket():
	#属性
	adult_ticket_normal =100
	adult_ticket_weekends = adult_ticket_normal *1.2
	child_ticket_normal = adult_ticket_normal
	child_ticket_weekends = child_ticket_normal*1.2
	def calculation(adult_ticket_normal,child_ticket_normal):
		s = adult_ticket_normal*2 + child_ticket_normal
		return(s)

调用:

Ticket.calculation(100,50) #250

有个疑问,就是我已经在内部函数里定义了变量100,但是外部还是需要传入参数,这是什么原因。

十四、魔法方法

魔法方法总是被双下划线包围,例如__init__。

魔法方法是面向对象的 Python 的一切,如果你不知道魔法方法,说明你还没能意识到面向对象的 Python 的强大。

魔法方法的“魔力”体现在它们总能够在适当的时候被自动调用。

魔法方法的第一个参数应为cls(类方法) 或者self(实例方法)。

  • cls:代表一个类的名称
  • self:代表一个实例对象的名称

1.基本的魔法方法

  • __init__(self[, ...]) 构造器,当一个实例被创建的时候调用的初始化方法
class Rectangle:  #定义了一个长方形/矩形类
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def getPeri(self):
        return (self.x + self.y) * 2 #周长
      def getArea(self):
        return self.x * self.y   
rect = Rectangle(4, 5) #rect是矩形结构的意思
print(rect.getPeri())  # 18
print(rect.getArea())  # 20   

这里注意到了一个特殊的__init__方法,是做什么用的?
详细解读python中的__init__方法

python中__init__方法有什么作用?

简单来说,__init__可以完成一些初始化的设定。
有了它,我们写Rectangle(4, 5) ,4,5这两个参数就会自动传入self.x和self.y中,如果没有,则会报错。
(不知道我理解的对不对?)

  • __new__(cls[, ...]) 在一个对象实例化的时候所调用的第一个方法,在调用__init__初始化前,先调用__new__
  • __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由 Python 解释器自动提供,后面的参数直接传递给__init__
  • __new__对当前类进行了实例化,并将实例返回,传给__init__的self。但是,执行了__new__,并不一定会进入__init__,只有__new__返回了,当前类cls的实例,当前类的__init__才会进入。

参考:
1.https://www.liaoxuefeng.com/wiki/1016959663602400/1017496031185408
2.https://github.com/datawhalechina/team-learning-program/blob/master/PythonLanguage/13.%20%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1.md

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值