欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Task07:类、对象与魔法方法

程序员文章站 2024-03-15 23:05:06
...

类与对象

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)用于删除属性。

练习题:

Task07:类、对象与魔法方法

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作为额外的第一个参数

Task07:类、对象与魔法方法

  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):

Task07:类、对象与魔法方法

repr(self):

Task07:类、对象与魔法方法

2. 算术运算符

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

Task07:类、对象与魔法方法
Task07:类、对象与魔法方法
Task07:类、对象与魔法方法

3. 反算术运算符

反运算魔方方法,与算术运算符保持一一对应,不同之处就是反运算的魔法方法多了一个“r”。当文件左操作不支持相应的操作时被调用。Task07:类、对象与魔法方法

4. 增量赋值运算符

Task07:类、对象与魔法方法

一元运算符、属性访问

Task07:类、对象与魔法方法
Task07:类、对象与魔法方法

描述符

描述符就是将某种特殊类型的类的实例指派给另一个类的属性。
Task07:类、对象与魔法方法

定制序列

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

容器类型的协议

Task07:类、对象与魔法方法
Task07:类、对象与魔法方法

迭代器Task07:类、对象与魔法方法

Task07:类、对象与魔法方法

把一个类作为一个迭代器使用需要在类中实现两个魔法方法 iter() 与 next() 。
Task07:类、对象与魔法方法

练习题

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

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