博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Python基础 - 09面向对象基础

Posted on 2021-10-16 15:35  Kingdomer  阅读(24)  评论(0编辑  收藏  举报

Python基础 - 09面向对象

面向对象:

类(有共同特征和行为的抽象的)、 对象(实例化的个体、个例)、   属性: 特征、   方法:  动作

 

一、类定义

所有的类名要求首字母大写,多个单词使用驼峰式命名。 如 ValueError、 StopIterable

class Phone:
    brand = 'huawei'

print(Phone)          # <class '__main__.Phone'>

# 使用类创建对象
hw = Phone()
print(hw)             # <__main__.Phone object at 0x0000006683783B20>
print(hw.brand)       # huawei,  如果对象自己的空间存在 brand属性,则不会去模型中取查找
hw.brand = 'honor'
print(hw.brand)       # honor

  

构造器__init__(self)

1. 找有没有一块空间是Phone类的

2. 利用Phone类,向内存申请一块和Phone一样的空间,0x0000009196583B20

3. 去 Phone 中找有没有 __init__, 如没有则 执行将开辟的内存空间 给对象 p1 -> 0x0000009196583B20

4. 如果有__init__,则会进入__init__方法执行里面动作。 动态的self 空间添加两个属性: brand, price

 

二、方法

种类: 普通方法/对象方法、 类方法、 静态方法、 魔术方法

2.1 普通方法

# 方法
class Phone:
    brand = 'xiaomi'

    def __init__(self):
        print('-----init-----')

    def call(self):
        print('self ---> ', self)
        print('打电话....')

xm1 = Phone()
print(xm1)            #            <__main__.Phone object at 0x0000009196583B20>
xm1.call()            # self --->  <__main__.Phone object at 0x0000009196583B20>   \n 打电话....

  

2.2 类方法

# 类方法
# 定义需要依赖装饰器 @classmethod
# 类方法中参数不是一个对象,而是类。   print(cls)     <class '__main__.Dog'>
# 类方法中只可以使用类属性。
# 类方法中不可使用普通方法。
class Dog:
    def __init__(self, nickname):
        self.nickname = nickname

    def run(self):
        print('{}在院子里跑圈'.format(self.nickname))

    @classmethod
    def test(cls):
        print(cls)
        # print(cls.nickname)   # AttributeError: type object 'Dog' has no attribute 'nickname'
        # print(self.nickname)  # NameError: name 'self' is not defined


d1 = Dog('球球')
d1.run()          # 球球在院子里跑圈
d1.test()         # <class '__main__.Dog'>

Dog.test()        # <class '__main__.Dog'>
#------------------------------------------
class Person:
    __age = 18

    def show(self):
        print('-->', Person.__age)

    @classmethod
    def update_age(cls):
        cls.__age = 20
        print('---->类方法')
        print(Person.__age)

    @classmethod
    def show_age(cls):
        print('修改后年龄:', cls.__age)


# print(Person.__age)   # AttributeError: type object 'Person' has no attribute '__age'
Person.update_age()     # ---->类方法   \n   20
Person.show_age()       # 修改后年龄: 20

  

2.3 静态方法

# 静态方法
# 需要装饰器  @staticmethod
# 静态方法是无需传递参数(cls, self)
# 只能访问类的属性和方法,对象的属性和方法是无法访问的。
# 加载时机同类方法

class Student:
    __age = 18
    name = 'lucy'

    def show(self):
        print('-->', Person.__age)

    @classmethod
    def update_age(cls):
        cls.__age = 20
        print('---->类方法')
        print(Person.__age)

    @classmethod
    def show_age(cls):
        print('修改后年龄:', cls.__age)

    @staticmethod
    def test():
        print('-->静态方法')
        # print(self.name)  # 语法错误
        print(Student.__age)


s = Student()
s.test()            # -->静态方法 \n 18

  

类方法 和 静态方法 

不同:  1. 装饰器不同    2. 类方法是有参数的, 静态方法是没有参数的

相同:  1. 只能访问类的属性和方法, 无法访问对象的  2. 都可以通过类名调用访问  3. 可以在创建对象之前访问。不依赖对象。

 

普通方法: 没有装饰器, 要依赖对象,每个普通方法都有一个self, 只有创建了对象才能调用。

 

2.4 魔术方法

格式: __名字__()

2.4.1 构造器 __init__(): 初始化, 触发时机: 初始化对象时触发。(不是实例化触发,是和实例化在一个操作中)

参数: 至少有一个self,接收对象  返回值: 无

class Person:
    name = 'zhangsan'

    def __init__(self):
        self.name = '张三'
        self.age = 18

    def eat(self):
        print('{}正在吃饭'.format(self.name))

    def run(self):
        print('{},今年{}岁,正在跑步'.format(self.name, self.age))


p1 = Person()
p1.name = '李四'
p1.eat()          # 李四正在吃饭
p2 = Person()
p2.eat()          # 张三正在吃饭
p2.run()          # 张三,今年18岁,正在跑步
# -----------------------------------------
class Person:
    name = 'zhangsan'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self, food):
        print('{}正在吃{}'.format(self.name, food))

    def run(self):
        print('{},今年{}岁,正在跑步'.format(self.name, self.age))


p3 = Person('王五', 11)
p3.eat('烤鸭')              # 王五正在吃烤鸭
p3.run()                   # 王五,今年11岁,正在跑步

2.4.2 __new__(): 实例化   触发时机: 实例化对象时触发

参数: 至少一个cls接收当前类   返回值: 必须返回一个对象实例

实例化对象是Object类底层实现, 其他类继承了Object的__new__才能实现实例化对象。

先触发__new__才会触发__init__

class Person:
    def __init__(self):
        print('-----> init')

    def __new__(cls, *args, **kwargs):
        print('--->new')

p = Person()  
print('p:',p)
'''          
--->new
p:  None         # 未实例化对象, p 未指向地址
'''

 

    def __new__(cls, *args, **kwargs):
        print('--->new')
        return object.__new__(cls, *args, **kwargs)     

'''
--->new      # 先实例化       
-----> init  # 后初始化
p:  <__main__.Person object at 0x000000B66357AFA0>
'''

 

    def __new__(cls, *args, **kwargs):
        print('--->new')
        # return object.__new__(cls, *args, **kwargs)
        return super(Person, cls).__new__(cls, *args, **kwargs)  # 正确

  

    def __new__(cls, name):
        print('--->new')
        return super(Person, cls).__new__(cls, name)

TypeError: object.__new__() takes exactly one argument (the type to instantiate)
--->new

 

class Person:
    def __init__(self, name):
        print('-----> init')
        self.name = name

    def __new__(cls, *args, **kwargs):
        print('--->new')
        pos = object.__new__(cls)    # 申请开辟内存空间0x8183A7BFA0, 然后返回给 __init__的 self,进行初始化
        print(pos)
        return pos


p = Person('Jack')    # --->new
print(p)              # None
print(p.name)         # Jack
'''
--->new
<__main__.Person object at 0x0000008183A7BFA0>
-----> init
<__main__.Person object at 0x0000008183A7BFA0>
'''

  

2.4.3 __call__: 对象调用方法, p() / p(param)

触发时机: 将对象当成函数使用时,默认调用此函数中内容

class Person:
    def __init__(self, name):
        print('-----> init')
        self.name = name

    def __new__(cls, *args, **kwargs):
        print('--->new')
        pos = object.__new__(cls)
        print(pos)
        return pos

    def __call__(self, name):
        print('----> call')
        print('执行对象得到参数为', name)

p = Person('Luck')
print(p.name)

p('aaa')

'''
--->new
<__main__.Person object at 0x00000040DD9BBFA0>
-----> init
Luck
----> call
执行对象得到参数为 aaa
'''

  

2.4.4 __del__ 删除对象

当一块空间没有了任何引用,默认执行__del__

python解释器,回收所有在本次执行过程中使用到的空间。Python底层自带垃圾回收,进行内存释放。

import sys
class Person:
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print('删除对象了')

p = Person('abc')
p1 = p
p2 = p
print(p1.name)            # abc
print(p2.name)            # abc
print(sys.getrefcount(p)) # 4   / p, p1, p2, sys 四个引用, 指向同一个地址

p1.name = 'tom'
print(p.name)             # tom
print(p2.name)            # tom

del p2                    # 删除p2 对地址的引用
print(p.name)             # tom
print(sys.getrefcount(p)) # 3 \n  删除对象了

  

2.4.5 __str__:  单纯打印对象名称,打印的是地址。

触发时机: 打印对象名称时, 自动触发去调用__str__里面的内容。

在__str__方法中添加return, return 后面的内容是打印对象输出的内容。

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

    def __str__(self):
        # print('对象str:', self.name)
return '对象str: {}'.format(self.name) t = Teacher('tt') print(t) # 对象str: tt