python笔记-09(再谈对象)

在之前关于面向对象的编程中,只是简单的介绍。先对该部分进行扩展。

在python2版本中,会发现__metaclass__ = type这样的开头,这表示将类定义为新式类。关于新式类与旧式类的区别可查看博文(https://blog.csdn.net/mrsun1/article/details/105569071)。

1、构造函数

构造函数用于创建类时的一些初始化过程,python的构造函数为__init__(self),如下所示

# 构造函数__init__()
class ClassTest1:
    def __init__(self):
        self.name = "tom"


classTest1 = ClassTest1()
print(classTest1.name)

结果
tom

构造函数也可以带形参

# 带参数的构造函数__init__(),__del__()析构函数用于对象销毁时调用
class ClassTest2:
    def __init__(self, value="tony"):
        self.name = value


classTest2 = ClassTest2(value="james")
print(classTest2.name)

结果
james

如果是两个类存在继承关系呢?

#继承关系下的构造函数调用
class ClassTest3:
    def __init__(self):
        self.name = "tom"
    def method(self):
        print(self.name)

class ClassTest4(ClassTest3):
    def __init__(self):
        pass

classTest4 = ClassTest4()
# 该种方式会出现错误,因为ClassTest4中没有属性name,但是其继承了基类的method方法
# 在该方法中使用到了name属性,所以报错。这也是因为在初始化ClassTest4是没有调用ClassTest3的
# 构造函数导致的
classTest4.method()

可以使用super或直接调用基类的构造函数执行基类的构造函数

class ClassTest3:
    def __init__(self):
        self.name = "tom"

    def method(self):
        print(self.name)


class ClassTest4(ClassTest3):
    def __init__(self):
        # 以前的方式调用基类的构造函数
        # ClassTest3.__init__(self)
        # 新的方式调用基类的构造函数
        # 使用super的好处在于可以直接调用其所有基类的构造函数
        super().__init__()
        pass


classTest4 = ClassTest4()
classTest4.method()

结果
tom

2、多态

多态是指同一行为具有不同的表现形式。

# 测试多态
class Dog:
    def __init__(self, name):
        self.name = name

    def run(self):
        print(self.name + " run")


class BlackDog(Dog):
    def run(self):
        print(self.name + "run")


class WhiteDog(Dog):
    def run(self):
        print(self.name + "run")


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

    def run(self, dog):
        print(self.name + " with " + dog.name + " run")


dog = Dog("狗")
# dog = WhiteDog("白狗")
# dog = BlackDog("黑狗")
person = Person("小明")
person.run(dog)

3、类方法、实例方法与静态方法

与java不同,python的类方法和静态方法只指不同的方法。类方法只需要访问类属性,静态方法既不需要访问类属性也不需要访问实例属性,实例方法既可以访问类属性也可以访问实例属性。

pyhton的类方法需要添加@classmethod注释,同时方法中需要传入cls表示类的参数。静态方法需要@staticmethod注释

# 测试类方法与静态方法
class Dog:
    # 类属性
    name = "tom"

    # 定义类方法(只需要访问类属性)
    @classmethod
    def eat(cls):
        print(cls.name + " eat ")

    # 定义静态方法(既不访问类属性也不访问实例属性)
    @staticmethod
    def help():
        print("help message")

    # 实例方法(既可以访问实例属性也可以访问类属性)
    def run(self):
        print("name:" + Dog.name + " color:" + self.color)

    # 构造方法
    def __init__(self, color):
        self.color = color


dog = Dog("black")
dog.eat()
dog.help()
dog.run()

结果
tom eat 
help message
name:tom color:black

 4、单例模式

单例是指不管new出多少对象,这些对象都是同一个对象,即其地址是同一个。__new__(cls, *args, **kwargs)是为对象分配内存空间的方法,同时分配完内存空间后需要进行返回否则创建的对象为None。

# 单例设计模式
class Dog:
    instance = None
    flag = False

    # 为对象分配空间
    def __new__(cls, *args, **kwargs):
        if Dog.instance is None:
            Dog.instance = super().__new__(cls)
        return Dog.instance

    def __init__(self):
        if Dog.flag:
            return
        print("开始初始化实例")
        Dog.flag = True


dog1 = Dog()
dog2 = Dog()
print(dog1)
print(dog2)

结果
开始初始化实例
<__main__.Dog object at 0x0000019BA19C53A0>
<__main__.Dog object at 0x0000019BA19C53A0>

5、模块

每个python文件就相当于一个模块,使用时可以导入其他模块进行使用,如下所示,在testmodule2.py文件中,使用__name__使得在引用该模块时后面的模块中的测试语句不会被调用。

testmodule2.py 文件中

# 模块测试
def hello():
    print("hello world")


class Dog:
    def eat(self):
        print("dog eat")


# 下面的代码其实是不需要的,同时别人在导入本模块时下面的代码会自动执行一遍
# 使用__name__可以解决,当本模块执行是__name__=__main__,当别人调用时__name__=该模块名称
# 这种方式通常用于模块测试
if __name__ == "__main__":
    print("模块中没有缩进的代码")



tetmodule.py文件中
# 模块测试

import random
from testmodule2 import Dog as D
from testmodule2 import hello

# __file__可以查看模块的完整路径
print(random.__file__)
dog = D()
dog.eat()
hello()

运行testmodule文件
E:\python38\lib\random.py
dog eat
hello world

6、包

创建包,包下会自动生成__init__.py文件,该包下的模块如果想被其他包中的模块调用,可以在__init__.py文件中导入,如下所示

package1包中有testpackage1.py的文件,在默认包下有个testpackage.py的文件,想要导入package1包下的模块testpackage1,需要在__init__文件中

from . import testpackage1
testpackage1.py文件

class Dog:
    def eat(self):
        print("eat")
testpackage.py文件

from package1 import testpackage1

dog = testpackage1.Dog()
dog.eat()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值