Task07:类、对象与魔法方法

类与对象

1、对象 = 属性 + 方法

1)封装:信息隐蔽技术

使用class 定义 Python 类,关键字后面紧跟类的名称、分号和类的实现。
! Python中的类名约定以大写字母开头

2)继承:子类自动共享父类之间数据和方法的机制

class MyList(list):
    pass


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

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

2、self (相当于 C++ 的 this 指针。)

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


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

3、 Python 的魔法方法

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,该死的,谁踢我...

4、公有和私有

在变量名或函数名前加上“__”两个下划线,函数或变量就变为私有。

私有属性
class JustCounter:
    __secretCount = 0  # 私有变量
    publicCount = 0  # 公开变量

    def count(self):
        self.__secretCount += 1
        self.publicCount += 1
        print(self.__secretCount)


counter = JustCounter()
counter.count()  # 1
counter.count()  # 2
print(counter.publicCount)  # 2

print(counter._JustCounter__secretCount)  # 2 Python的私有为伪私有
print(counter.__secretCount)  
# AttributeError: 'JustCounter' object has no attribute '__secretCount'
私有方法
class Site:
    def __init__(self, name, url):
        self.name = name  # public
        self.__url = url  # private

    def who(self):
        print('name  : ', self.name)
        print('url : ', self.__url)

    def __foo(self):  # 私有方法
        print('这是私有方法')

    def foo(self):  # 公共方法
        print('这是公共方法')
        self.__foo()


x = Site('老马的程序人生', 'https://blog.csdn.net/LSGO_MYP')
x.who()
# name  :  老马的程序人生
# url :  https://blog.csdn.net/LSGO_MYP

x.foo()
# 这是公共方法
# 这是私有方法

x.__foo()
# AttributeError: 'Site' object has no attribute '__foo'

5、继承

定义:

class DerivedClassName(BaseClassName):
    <statement-1>
    .
    .
    .
    <statement-N>

!BaseClassName(示例中的基类名)必须与派生类定义在一个作用域内

6、组合

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("水池里面有乌龟%s只,小鱼%s条" % (self.turtle.num, self.fish.num))


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

7、类、类对象和实例对象

类对象:创建一个类,其实也是一个对象也在内存开辟了一块空间,称为类对象,类对象只有一个。

实例对象:就是通过实例化类创建的对象,称为实例对象,实例对象可以有多个。

类属性:类里面方法外面定义的变量称为类属性。类属性所属于类对象并且多个实例对象之间共享同一个类属性,说白了就是类属性所有的通过该类实例化的对象都能共享。

实例属性:实例属性和具体的某个实例对象有关系,并且一个实例对象和另外一个实例对象是不共享属性的,说白了实例属性只能在自己的对象里面使用,其他的对象不能直接使用,因为self是谁调用,它的值就属于该对象。

8、绑定

Python 对象的数据属性通常存储在名为.__ dict__的字典中,我们可以直接访问__dict__,或利用 Python 的内置函数vars()获取.__ dict__。

class CC:
    def setXY(self, x, y):
        self.x = x
        self.y = y

    def printXY(self):
        print(self.x, self.y)


dd = CC()
print(dd.__dict__)
# {}

print(vars(dd))
# {}

print(CC.__dict__)
# {'__module__': '__main__', 'setXY': <function CC.setXY at 0x000000C3473DA048>, 'printXY': <function CC.printXY at 0x000000C3473C4F28>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}

dd.setXY(4, 5)
print(dd.__dict__)
# {'x': 4, 'y': 5}

print(vars(CC))
# {'__module__': '__main__', 'setXY': <function CC.setXY at 0x000000632CA9B048>, 'printXY': <function CC.printXY at 0x000000632CA83048>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}

print(CC.__dict__)
# {'__module__': '__main__', 'setXY': <function CC.setXY at 0x000000632CA9B048>, 'printXY': <function CC.printXY at 0x000000632CA83048>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}

9、内置函数

issubclass(class, classinfo) 方法用于判断参数 class 是否是类型参数 classinfo 的子类。一个类被认为是其自身的子类。
classinfo可以是类对象的元组,只要class是其中任何一个候选类的子类,则返回True。
isinstance(object, classinfo) 方法用于判断一个对象是否是一个已知的类型,类似type()。
type()不会认为子类是一种父类类型,不考虑继承关系。
isinstance()会认为子类是一种父类类型,考虑继承关系。
如果第一个参数不是对象,则永远返回False。
如果第二个参数不是类或者由类对象组成的元组,会抛出一个TypeError异常。
hasattr(object, name)用于判断对象是否包含对应的属性。
getattr(object, name[, default])用于返回一个对象属性值。
setattr(object, name, value)对应函数 getattr(),用于设置属性值,该属性不一定是存在的。
delattr(object, name)用于删除属性。

练习题:

在这里插入图片描述

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

2、怎么定义私有⽅法?

在方法名称前加上两个下划线__即可定义为私方法

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

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

代码需要缩进至前排,类中的方法内都缺少self作为额外的第一个参数

在这里插入图片描述

  def __init__(self,kid,adult,day):
        self.kid=kid
        self.adult=adult
        self.day=day
    def price(self):
        if self.day in range(6):
            print(100*self.adultnum+50*self.kidnum)
        else:
            print((100*self.adultnum+50*self.kidnum)*1.2)
m=ticket(1,2,1)
m.price()   #250

魔法方法

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

cls:代表一个类的名称

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

1. 基本的魔法方法

init(self[, …]) 构造器,当一个实例被创建的时候调用的初始化方法

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

class A(object):
    def __init__(self, value):
        print("into A __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into A __new__")
        print(cls)
        return object.__new__(cls)


class B(A):
    def __init__(self, value):
        print("into B __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into B __new__")
        print(cls)
        return super().__new__(cls, *args, **kwargs)


b = B(10)

若__new__没有正确返回当前类cls的实例,那__init__是不会被调用的,即使是父类的实例也不行,将没有__init__被调用。

__new__方法主要是当你继承一些不可变的 class 时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。

del(self) 析构器,当一个对象将要被系统回收之时调用的方法。

str(self):

###

repr(self):

在这里插入图片描述

2. 算术运算符

类型工厂函数,指的是“不通过类而是通过函数来创建对象”。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 反算术运算符

反运算魔方方法,与算术运算符保持一一对应,不同之处就是反运算的魔法方法多了一个“r”。当文件左操作不支持相应的操作时被调用。在这里插入图片描述

4. 增量赋值运算符

在这里插入图片描述

一元运算符、属性访问

在这里插入图片描述
在这里插入图片描述

描述符

描述符就是将某种特殊类型的类的实例指派给另一个类的属性。
在这里插入图片描述

定制序列

协议(Protocols)与其它编程语言中的接口很相似,它规定你哪些方法必须要定义。然而,在 Python 中的协议就显得不那么正式。事实上,在 Python 中,协议更像是一种指南。

容器类型的协议

在这里插入图片描述
在这里插入图片描述

迭代器在这里插入图片描述

在这里插入图片描述

把一个类作为一个迭代器使用需要在类中实现两个魔法方法 iter() 与 next() 。
在这里插入图片描述

练习题

1、上面提到了许多魔法方法,如__new__,init, str,rstr,getitem,__setitem__等等,请总结它们各自的使用方法。

1) __new__方法主要是当你继承一些不可变的 class 时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径
2)init(self[, …]) 构造器,当一个实例被创建的时候调用的初始化方法
3)__str__用来在打印对象,用%s格式化以及强制转换数据类型时触发
4)__repr__也是用来rper()内置函数和用%s格式化的时候触发
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值