python面向对象(类)笔记

1.创建和使用类

python中通过class创建类,下面创建一个Animal类,类名首字母一般大写。__init__是一个特殊的方法,用来初始化对象属性

# 创建类
class Animal(object):
    num = 18    # 可在类中创建此类字段
    
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eating(self):
        print(f'the {self.name} is eating')

    def singing(self, songname):
        print(f'the {self.name} is singing a song ,the song is {songname}')

# 使用类
animal = Animal('rabbit', '1')
animal.eating()
animal.singing('两只老虎')
print(animal.num)
"""
输出结果:
rabbit is eating
rabbit is singing a song ,the song is 两只老虎
18
"""

2.属性私有化

python 中属性的私有化是通过给属性前加两个下划线来实现的,示例如下:

class Animal(object):
    def __init__(self, gender, age):
        self.__gender = gender
        self.__age = age

    def __get_gender(self):
        animal_gender = self.__gender
        print(animal_gender)

animal = Animal('xx')
animal.__get_gender()   
# TypeError: __init__() missing 1 required positional argument: 'age'

print(animal.__age)
# TypeError: __init__() missing 1 required positional argument: 'age'

如上便实现了私有化。

但是,python的私有化并不是真正的私有化,python的一切类方法和属性都是“公开的”,它的私有化,只是改变了名字而已,只要我们知道它改变名字的规律,私有的属性我们都能访问到。之所以python会如此设置,是因为这个理念:“开放要比封闭好,程序员得为自己的行为负责”

下面是访问私有属性的代码:

class Animal(object):
    def __init__(self, gender, age):
        self.__gender = gender
        self.__age = age

    def __get_gender(self):
        animal_gender = self.__gender
        print(animal_gender)

animal = Animal('xx', 3)
animal._Animal__get_gender()

# 输出    xx

3.类中的几种方法

3.1 类方法

类方法用@classmethod声明,代码如下:

class Animal(object):
    num = 18  

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

    def eating(self):
        print(f'{self.name} is eating')
        return ''

    def singing(self, songname):
        print(f'the {self.name} is singing a song ,the song is {songname}')

    @classmethod 	# 在此使用了类方法
    def action(cls):
        a1 = cls('tutu', 4)    # 注意此句
        return a1.eating()

animal = Animal.action()
print(animal)
# tutu is eating

用@classmethod声明类方法后,定义函数时,pycharm会自动在括号里填充cls,cls指的是当前类,可以直接用其创建对象,也可以使用类中的方法,如上所示。

3.2 静态方法

在创建类时,对象方法都是给对象发送消息的,实际上我们并不需要每个类方法都是对象方法,比如你不确定某些对象能否合理创建时,就可以在此类中创建一个静态方法,专门用于判断能否合理 创建对象。例如,你创建了一个成年人类,只有成年人才能访问其中方法,静态方法用@staticmethod声明:


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

    @staticmethod
    def judge_adult(age):
        return age > 18

    def wangba(self):
        print(f'{self.name}可以去网吧')
        return

    
p1 = Person('jony', 'male')
if p1.judge_adult(17):
    p1.wangba()
else:
    print('you are not a adult')
    
# you are not a adult

4. 对象属性的操作

我们可以对对象的属性进行增删改查

class Animal(object):
    def __init__(self, name, age, breed):
        self.name = name
        self.age = age
        self.breed = breed

    def get_informations(self):
        print(self.name, self.age, self.breed)

animal = Animal('doudou', 6, 'dog')
animal.get_informations()
# doudou 6 dog
animal.age = 7 		# 可采用此形式直接改变属性值
animal.get_informations()
# doudou 7 dog

# 可通过getattr(对象,属性)直接获取属性值
print(getattr(animal, 'name')) 
# doudou

# 可通过setattr(对象, 属性, 值)给对象修改属性值
setattr(animal, 'breed', 'cat')
print(getattr(animal, 'breed'))
# cat

# 可通过del(属性)删除对象对应属性
del animal.breed
print(animal.breed)
# AttributeError: 'Animal' object has no attribute 'breed'

注意: 使用del删除对象对应属性时,并不会把类中的属性也直接删除,下次用此类新创建一个对象时,该属性依然可用。

5.getter和setter

实际开发中,我们并不是以双下划线来将属性设置为私有,而是用单下划线来表示这个属性是受保护的,这个属性并不是私有,你仍然可以通过访问它的下划线形式来进行增删改查。

属性名前加单下划线,当我们希望在给它赋值前或者获取其属性前做点其他事,可以用getter和setter。

class Animal(object):
    def __init__(self, name, age, breed):
        self._name = name 	# 将属性名前加下划线,表示受保护
        self._age = age
        self._breed = breed

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if isinstance(value, int):
            if 0 < value <=150:
                self._age = value
            else:
                print('年龄不符合常理')


animal = Animal('doudou', 6, 'dog')
print(animal._age)
# 6
animal.age = 180
# 年龄不符合常理

但是,我们仍然可以通过下划线方法来访问和修改受保护的属性,一般情况下别那么做
animal._age = 180
print(animal._age)
# 180

6.类中的内置属性

  • __name__ : 获取类的名字
  • __class__ : 获取当前对象对应的类
  • __doc__ : 获取当前类的说明文档
  • __dict__ : 获取所有的字段和属性及其对应的值
  • __slots__ : 控制可修改的属性
class Animal(object):
    """
    动物类,用于测试
    """
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eating(self):
        print(f'the {self.name} is eating')

    def singing(self, songname):
        print(f'the {self.name} is singing a song ,the song is {songname}')
        
animal = Animal('qiqi', 6)
print(animal.fun1())
# Animal

print(animal.__class__)
# <class '__main__.Animal'>

print(Animal.__doc__)
#  动物类,用于测试

print(animal.__dict__)
# {'name': 'qiqi', 'age': 6}

print(Animal.__dict__)
# {'__module__': '__main__', '__doc__': '\n    动物类,用于测试\n    ', '__init__': <function Animal.__init__ at 0x0000022A69408E18>, 'eating': <function Animal.eating at 0x0000022A69408EA0> ......

其中,__slots__单独测试如下:

class Animal(object):

    __slots__ = ('name', 'age', 'breed')
    def __init__(self, name, age, breed):
        self.name = name
        self.age = age
        self.breed = breed

    def eating(self):
        print(f'the {self.name} is eating')

    def singing(self, songname):
        print(f'the {self.name} is singing a song ,the song is {songname}')

    @classmethod
    def fun1(cls):
        return cls.__name__

animal = Animal('qiqi', 6, 'fish')
animal.name = 'ggbong'
animal.gender = 'male'
# AttributeError: 'Animal' object has no attribute 'gender'
当把 __slots__去掉后,不报错

7.继承多态

7.1继承

子类可以从父类那里继承属性和方法,通过super().__init__调用,也可以通过super().方法调用指定方法,静态方法不能用。

子类除了能使用父类的方法外,还可以自定义一些方法,所以子类比父类拥有更多的能力。

class Animal(object):		# 父类
    num = 2

    def __init__(self, name=None):
        self.name = name
        self.gender = 'male'

    def playing(self):
        print('{} is playing'.format(self.name))

    @staticmethod
    def fun1():
        return 'a+b'    # 静态方法,期待返回 'a+b'


class Cat(Animal):		# 子类
    voice = 'mia~'

    def __init__(self, name, age):
        super().__init__(name)  # 调用当前父类的init方法
        self.color = 'black'
        self.breed = 'jaffe'

    def cat_play(self):
        super().playing()    # 继承的父类方法
        return None

    def getsome(self):
        super().fun1()    # 父类中的静态方法
        return None


cat = Cat('caffe', 6)
print(cat.color)
# black

print(cat.cat_play())
# caffe is playing

print(cat.getsome())    # 尝试调用静态方法
# None
7.2多继承

关于多继承,示例如下:

class A:
    def message(self):
        print('A')


class B:
    def message(self):
        print('B')


class C(A, B):
    def message(self):
        super().message()
        print('C')


class D(B, A):
    def message(self):
        super().message()
        print('D')


C().message()
# A
# C
# 发现继承的是前面那个父亲

D().message()
# B
# D
7.3 多态

子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态。

下面是来自Github上jackfrued的例子:

from abc import ABCMeta, abstractmethod


class Pet(object, metaclass=ABCMeta):
    """宠物"""

    def __init__(self, nickname):
        self._nickname = nickname

    @abstractmethod
    def make_voice(self):
        """发出声音"""
        pass


class Dog(Pet):
    """狗"""

    def make_voice(self):
        print('%s: 汪汪汪...' % self._nickname)


class Cat(Pet):
    """猫"""

    def make_voice(self):
        print('%s: 喵...喵...' % self._nickname)


def main():
    pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]
    for pet in pets:
        pet.make_voice()


if __name__ == '__main__':
    main()
    
""" 输出:
旺财: 汪汪汪...
凯蒂: 喵...喵...
大黄: 汪汪汪...
"""

Python从语法层面并没有像Java或C#那样提供对抽象类的支持,但是我们可以通过abc模块的ABCMeta元类和abstractmethod包装器来达到抽象类的效果,如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)。上面的代码中,DogCat两个子类分别对Pet类中的make_voice抽象方法进行了重写并给出了不同的实现版本,当我们在main函数中调用该方法时,这个方法就表现出了多态行为(同样的方法做了不同的事情)。

关于面向对象的知识纷杂繁多,对于“一切皆为对象”的python而言,面向对象的知识无时无刻不在使用。上面的基础操作不过尔尔,具体灵活运用,还需自身多实践。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值