1

Python(四)之面向对象(类、私有属性、私有方法、静态方法、类方法、继承、多态、鸭...

 3 years ago
source link: https://blog.csdn.net/weixin_46382560/article/details/115583795
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

申明:资料来源于网络及书本,通过理解、实践、整理成学习笔记。

类(Class)

类的定义与使用

类必须在被定义后才能使用,定义一个类也就是定义这一类对象的模板,定义它的属性和方法。python中提供了class关键字来声明一个类,class中有成员属性和成员方法。

类的格式:
class [类名]:
	[语句块]
类的定义:
class NewClass:
	pass
类的使用:
# 实例化类
new = NewClass()

类的构造方法

在创建实例时,很多类都需要特定的初始状态,所以一个类可以定义一个特殊的方法,叫做构造方法。在python中,构造函数就是类的__int__方法。当一个类定义了__int__方法,在类实例化是会自动调用__int__方法。
注意:构造方法的返回值必须是"None"

class Human:
    def __init__(self):
        print('我是人类')
        
human = Human()
执行结果:
我是人类

类的属性与方法

  • 属性:又称为成员变量或类变量,必须要使用"self"加上点的方式赋值,不能直接定义变量。直接定义的变量的生命周期只会在函数内,函数执行完变量就会被销毁。
    class Human:
        def __init__(self, name):
            self.name = name	#正确的定义变量方式
            age = 	3			#错误的定义变量方式
    
    human = Human('周星驰')
    print(human.name)
    
    执行结果:
    周星驰
    
  • 方法:在类中定义的函数称之为方法。类的方法和函数定义的方法基本相同,但方法一定要在类里并且第一个参数必须是"self"
    class Human:
        def __init__(self, name):
            self.name = name
    	# 方法
        def run(self):
            print('生命不息,运动不止')
    
    human = Human('周星驰')
    human.run()
    
    执行结果:
    生命不息,运动不止
    

私有属性与私有方法

  • 私有属性:在上面的例子中可以看到实例可以获取和修改属性的值。但如果我们需要限制实例修改属性的话就要用到私有属性。定义私有属性只需要在定义属性名字的时候使用两条下划线作为开头,python解释器就认为这个属性时私有的,外部不能随便访问这个属性。
    class Human:
        def __init__(self, name):
            self.__name = name
    
    human = Human('周星驰')
    human.__name()
    
    执行结果:
    AttributeError: 'Human' object has no attribute '__name'
    
    虽然我们在构造方法给"__name"赋值了,但是在实例中不能直接访问到这个私有变量。我们可以使用这个特效保护一些不想让用户随便修改的属性。
    class Human:
        def __init__(self):
            self.__name = None
    
        def set_name(self, name):
            if not isinstance(name, str):
                print('名字必须是字符串')
                return False
            if len(name) > 4:
                print('名字的字符数不嫩大于4!')
                return False
            elif len(name) <= 0:
                print('名字的字符数必须大于0!')
                return False
            self.__name = name
    
        def play(self):
            print('我的名字是:', self.__name)
    
    human = Human()
    human.set_name(1)
    human.set_name('')
    human.set_name('阿姆斯特朗')
    human.set_name('周星驰')
    human.play()
    
    执行结果:
    名字必须是字符串
    名字的字符数必须大于0!
    名字的字符数不嫩大于4!
    我的名字是: 周星驰
    
  • 私有方法:私有方法与私有变量相似,也是只能在类内部被调用,实例不能直接调用。
    class Human:
        def __init__(self, name):
            self.name = name
    
        # 方法
        def __run(self):
            print('生命不息,运动不止')
    
    human = Human('周星驰')
    human.__run()	#错误
    
    执行结果:
    AttributeError: 'Human' object has no attribute '__run'
    

静态方法与类方法

  • 静态方法:与类变量有点相似,在定义类时就已经被分配好了,并不绑定类也不绑定实例,相当于给方法添加了一个前缀。定义静态方法需要加入装饰器语法"@staticmethod"。静态方法不再需要"self",在调用时也不需要实例化。
    class Human:
    	name = '周星驰'
    	
        @staticmethod
        def run():
            print('生命不息,运动不止')
    
    Human.run()
    
    执行结果:
    生命不息,运动不止
    
  • 类方法:该方法绑定在定义的类上,而不是绑定在实例上。定义静态方法需要加入装饰器语法"@classmethod",类方法都有一个初始的参数"cls",这个参数指向的是定义的类本身,所有类方法可以读取和修改类变量。
    class Human:
        name = '周星驰'
    
        @classmethod
        def run(cls):
            print(cls.name, '生命不息,运动不止')
    
    Human.run()
    
    执行结果:
    周星驰 生命不息,运动不止
    

继承与多态

面向对象编程具有三大特效:封装性、继承性、多态性。

在一个类的基础上制定一个新类,这个类不仅可以继承原来类的属性和方法,还可以添加新的属性和方法。原来的类叫父类,新的类叫子类。python还支持多重继承,也就是说一个子类能继承多个父类。但子类不能调用父类的私有变量和私有方法。

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

    def eat(self):
        print('人是铁,饭是钢')


class YellowHuman(Human):
    pass

yellow_human = YellowHuman('周星驰')
yellow_human.eat()

执行结果:
人是铁,饭是钢

如上所示,"YellowHuman"这个类没有写"eat"方法,但是继承了"Human"类,所有就相当于拥有了"Human"类中的所有方法,执行"yellow_human.eat()“语句的结果为"人是铁,饭是钢”

当子类和父类存在相同的方法时,子类的方法会覆盖父类的方法,这样的代码在运行时总是会调用子类的方法,这就是多态

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

    def run(self):
        print('生命不息,运动不止')


class YellowHuman(Human):
    def run(self):
        print('生命在于运动')

class BlackHuman(Human):
    def run(self):
        print('你想拥有强壮的肌肉吗')

yellow_human = YellowHuman('周星驰')
yellow_human.run()
balck_human = BlackHuman('巨石强森')
balck_human.run()

执行结果:
生命在于运动
你想拥有强壮的肌肉吗

鸭子类型(Duck Typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是有继承自特定的类或实现特定的接口决定的,而是由当前方法和属性的集合决定的。
鸭子类型通常得意于不测试方法和函数得到类型,而是依赖文档、清晰的代码和测试来确保正常使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的类型检查,从而影响了鸭子类型的益处和可升缩性,并约束了语言的动态特性。

class YellowHuman:
    def run(self):
        print('生命在于运动')

class BlackHuman:
    def run(self):
        print('你想拥有强壮的肌肉吗')

def human_run(human):
    human.run()

yellow_human = YellowHuman()
balck_human = BlackHuman()

human_run(yellow_human)
human_run(balck_human)

执行结果:
生命在于运动
你想拥有强壮的肌肉吗

这个例子中虽然没有使用继承,但是我们任然可以实现"多态",这也是"多态"的一种实现方式。

类变量与实例变量的区别

类变量:不需要实例化就能直接使用,相当于绑定在类上,而不是绑定在实例上。但是类变量在实例中也是可以被调用的。可在类的所有实例之间共享的值

class Human:
    name = '名字'	#类变量

print(Human.name)
human = Human()
print(human.name)

执行结果:
名字
名字

实例变量:实例化之后,每个实例单独拥有的变量。

class Human:
    def __init__(self, name):
        self.name = name	#实例变量

human = Human('名字')
print(human.name)

执行结果:
名字

类变量和实例变量的区别在于:类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而实例变量则属对象私有,某一个对象将其值改变,不影响其他对象。

一个坚持学习,坚持成长,坚持分享的人,即使再不聪明,也一定会成为优秀的人!

如果看完觉得有所收获的话,记得一键三连哦,谢谢大家!


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK