博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 面向对象
阅读量:6673 次
发布时间:2019-06-25

本文共 9178 字,大约阅读时间需要 30 分钟。

1.构造函数

构造函数:__init__(参数列表) :在使用类创建对象时自动调用。
注意:如果自己不写构造函数,系统默认也会加上一个空的构造函数。
对象属性的优先级高于类属性,当对象调用属性时,如果有对象属性时,先获取对象属性的值;如果没有对象属性,会去找同样名字的类属性;如果没有同样名字的类属性,返回一个错误。
class Person():    # 直接写在class中的属性叫类属性(可以通过类名直接调用)    # name = ""    # age = 0    # 默认的构造函数(在init方法中的属性叫对象属性)    # __init__函数没有返回值,不能写return    # def __init__(self):    #     pass    # 自己重新写构造函数时,只能更改参数列表及函数体,不能写return这条语句    # def __init__(self):    #     print("我显示的是init函数")    def __init__(self, name, age, weight=30.0):        print("小兔子乖乖")        # 对象属性(定义在构造函数中的属性为对象属性)        self.name = name        self.age = age        self.weight = weight    # 建议:一个类中最好只有一个init函数,如果写了多个,程序不会报错,    # 但是只会执行最后一个写的init函数    def eat(self):        print("person--eat")    def sleep(self, hours):        print("我睡了%d小时" % hours)        # 建议使用关键字 实例化对象    per1 = Person(name="Lily", age=30, weight=50.0)

2.self__class__

self:当前类的实例对象,但是在类中用self表示。
哪个对象调用带有self参数的方法时,self就指向哪一个对象。

__class__: 代表当前类的类名。

self:不是关键字,换成其他的词语也可以,只要类中的成员方法至少有一个形参即可,第一个形参就代表当前类的实例对象

3.析构函数

析构函数:
__del__() : 释放对象时调用,销毁对象时调用。
class Person():    # 构造函数    def __init__(self, name):        self.name = name    def __del__(self):        print('析构函数' + self.name)per1 = Person('tom')per2 = Person('lucy')per3 = Person('lily')# del per3.name 删除对象属性# del per3 # 手动删除优先级高 先删除lily 然后执行类里的析构函数,系统的自动回收def fun1():    per4 = Person('Json') # 局部变量    print(per4.name)fun1() # Json 析构函数Json 用完函数后 per4 被析构函数回收

4.__str__函数

在使用print打印对象时会自动调用,这个方法是给用户使用的,是描述对象的方法。
class Person():    def __init__(self, name, age, sex):        self.name = name        self.sex = sex        self.age = age    # 可以在类中重新写__str__方法    # 要求必须有返回值,返回值类型str类型    def __str__(self):        sexStr = ""        if self.sex == 1:            sexStr = "女"        elif self.sex == 0:            sexStr = "男"        return "姓名为%s, 年龄为%d,性别为%s" %(self.name, self.age, sexStr)

5.访问限制

私有属性子类不能继承,子类的对象不能使用
实例对象不能直接访问私有属性
__age,因为python解释器把
__age私有属性变成了
_Person__age, 我们就可以通过
_Person__age访问私有属性
__age。强烈建议:不要这么干
class Person():    def __init__(self, name, age, weight, height):        # 公有属性:能够在当前类、当前类的实例对象、子类中均能使用        self.name = name        # 私有属性: 只能在当前类中使用        # 格式:__属性名(只在属性名前面加两个下划线)        self.__age = age        # 格式:__变量名__:在python中属于特殊变量,可以直接访问,类似公有属性        self.__weight__ = weight        # 格式: _变量名:在python中能够正常访问,类似公有属性,但是,当我们        # 看到这种属性时,把它当成是私有属性使用。        # _变量名(虽然我现在能直接访问并使用,但请把我当成私有属性,不要用        # 对象直接访问)        self._height = height    # set方法:赋值    def setAge(self, age):        if age < 0:            self.__age = 20        else:            self.__age = age    # get方法: 取值    def getAge(self):        return self.__age + 20    def setName(self, name):        self.name = name    def getName(self):        return self.name

6.继承

class Animal():    def __init__(self, name, color, age):        self.name = name        self.age = age        # 私有属性        self.__color = color    def run(self):        print(self.__color)        print("run")    def eat(self):        print("eat")class Cat(Animal):    def __init__(self, name, age, color, miao):        # 调用父类的__init__方法        # 父类名称.__init__(self, 根据父类形参赋值实参)        Animal.__init__(self, name, color, age)        # 使用super关键字调用init方法(同上)        # super(Cat, self).__init__(name, color, age)        # 子类可以有自己独有的属性        self.miao = miao

7.多重继承和多继承

单继承:一个子类只有一个父类
多重继承:子类有父类,父类又有父类 : 父类->子类->子子类。。。。。
多继承: Son -> Father,Mother
注意:如果父类们中的方法名相同,默认调用小括号中排在前面的父类中的方法(就近原则)

8.类方法及静态方法

类方法
@classmethod
类方法一般来说使用类名调用。
类方法类和对象均能调用,但是不管是类还是对象调用,cls都代表类;比如当前例子中,cls就代表Person,cls不是关键字,使用其他形参名称也可以,总之,类方法的第一个形参就代表类。

静态方法 @staticmethod

静态方法一般来说不是给对象是用的,一般使用类名调用
静态方法就是一个普通函数,不会默认需要传参数
类和对象均能调用,但一般使用类名调用

class Person():    # 对象方法,使用实例对象调用    def eat(self):        print("eat")    # 类方法  @classmethod    @classmethod    def play(cls, a, b):        print("类方法", a+b)        print(cls)    # 静态方法  @staticmethod    @staticmethod    def run(num1, num2):        print(num1 + num2)

9.动态添加属性及方法及__slots__属性

from types import MethodTypeclass Person():    def run(self):        print("run")    pass# 动态添加属性per1 = Person()per1.name = "Lily"print(per1.name)# 动态添加方法def say(self):    print("say")# MethodType(函数名称, 当前实例对象的名称)# 把当前的实例对象传递给函数的第一个形参per1.saying = MethodType(say, per1)per1.saying()
思考:如果我们要限制动态添加属性或方法的个数及名称怎么办?比如我们只能动态添加name及age属性,run方法。为了达到要求,python允许在定义类时,定义一个特殊的属性
__slots__属性变量,
__slots__属性可以限制动态添加的属性及方法的名称。
__slots__ :使用元组的方式赋值
注:
__slots__定义的属性只对当前类有效,对它继承的子类无效;
如果子类中也定义了
__slots__属性,这样定义的属性的个数为子类本身的内容加上父类中定义的内容。
class Student():    __slots__ = ("name", "age", "run")    passstu1 = Student()stu1.name = "Tom"# stu1.weight = 56.7  # 错误,不允许添加def run(self, a, b):    print("run", a+b)stu1.run = MethodType(run, stu1)stu1.run(2,3)

10.@property

@property 装饰器
@property: 可以使对象通过点方法访问私有属性。
class Person():    def __init__(self, name, age):        # 公有属性        self.name = name        # 私有属性        self.__age = age    @property    def age(self):        return self.__age        @age.setter    def age(self, age):        if age < 0:            age = 1        self.__age = ageper1 = Person(name="二胖", age=1)# 如果属性为公有属性,对象可以直接调用进行更改或使用# 这样,不安全,数据可以直接被重新赋值,而且没有任何限制条件。# 相当于调用set方法,现在调用的是加了@age.setter装饰器的方法per1.age = 99# 相当于调用get方法,现在调用的是加了@property装饰器的方法print(per1.age)

11.运算符重载

class Person():    def __init__(self, num):        self.num = num    # 打印对象时调用    def __str__(self):        return "目前num为:" + str(self.num)    # 运算符重载    def __add__(self, other):        return Person(self.num + other.num)    def __mul__(self, other):        return Person(self.num * other.num)p1 = Person(100)print(p1)p2 = Person(266)print(p2)print(p1 + p2)  # p1.__add__(p2)   __add__(self, other)Person(111)Person(111)print(p1 * p2)__init__: 构造函数__del__:析构函数__str__:打印对象__add__:加运算__mul__:乘运算__sub__:减运算__mod__:余运算__div__:除运算__pow__:幂运算

12.抽象类

在开发中,我们遇到的所有事物都是对象,对象是通过类创建的。但是不是所有的类都是用来描述对象的。如果一个类中没有足够的条件信息来描述一个具体的事物/对象,而需要其他具体的类来辅助他,那么,这样的类我们称之为抽象类。

抽象类中可以有抽象方法,一般包含抽象方法的类都是抽象类。

抽象方法可以不包含任何方法实现的代码,只有一个方法名字,但是,在子类中要求必须实现该抽象方法,否则,子类也为抽象类。

类是从一堆对象中抽取相同的属性及方法得出的,抽象类就是从一堆类中抽取相同的属性及方法得出的。

抽象类不能实例化对象。

1、定义抽象类
在定义抽象类之前,我们需要导入模块abc中的
ABCMeta类(抽象基类的元类)(Metaclass for defining Abstract BaseClass)。在定义抽象类时,我们需要在代码中加入 metaclass=ABCMeta,指定该类的元类为ABCMeta元类:创建一个类的类。
抽象类不能实例化对象。
抽象类一般都用作父类。

2、定义抽象方法

在定义抽象方法之前,我们需要导入模块abc中的abstractmethod类。
在定义抽象方法时,我们需要在方法前面加上@abstractmethod修饰词。
因为抽象方法一般不需要在抽象类中实现,我们只需要在抽象方法的函数体中写一条pass语句即可。

3、实现类

实现类为抽象类的子类。
如果实现类不实现父类(抽象类)中的抽象方法,那么该类也是抽象类;
如果实现类实现了父类(抽象类)中的抽象方法,那么该类就是普通类,可以实例化对象。

from abc import ABCMeta, abstractmethod# 定义抽象类class Animal(metaclass=ABCMeta):    # 定义属性    def __init__(self, color):        self.color = color    # 对象方法    def eat(self):        print("Animal--eat")    # 定义抽象方法    @abstractmethod    def play(self):        pass# 创建实现类(以一个抽象类为父类)class Cat(Animal):    def __init__(self, color, name):        Animal.__init__(self, color)        self.name = name    # 子类实现父类的抽象方法    def play(self):        print("cat--play")cat1 = Cat(color="black", name="旺财")print(cat1.color)

13.接口

真正的接口中不能定义变量,接口中只能有抽象方法。

1.什么是接口 interface,接口都是当作父类使用。

子类实现接口中的抽象方法。
在python中没有interface这个关键字,我们目前所写的接口只是通过抽象类仿写,
所以,目前,接口可以认为就是一个类,一个只包含抽象方法并且不能实例化对象的类。其子类如果想要实例化对象,必须实现接口中所有的抽象方法。

2.为什么要使用接口?

接口本身就是一系列方法的声明,一些特殊方法的集合,一个接口中只有方法的声明,但是没有方法的实现,这些特殊的方法要在不同的类之间进行不同的实现。接口本身是用于封装代码的。

例子:鸟类和昆虫类都有飞行的行为,功能相同,但实现内容不同,二者如果抽象出一个类不太方便,但可以抽象一个接口,用于飞行行为的封装。

3.注意:一般在接口中只有方法的声明,没有方法的实现。在接口中不能出现变量。

from abc import abstractmethod# 定义接口class Interface: # 仿写接口    # 定义抽象方法    @abstractmethod    def fly(self):        pass    # ...# 定义接口的实现类class Bird(Interface):    def __init__(self, leg):        self.leg = leg    def egg(self):        print("鸟生蛋")    def fly(self):        print("小鸟飞的高")class Insect(Interface):    def __init__(self, leg):        self.leg = leg    def spawn(self):        print("昆虫产卵")    def fly(self):        print("昆虫飞的低")b1 = Bird(2)b1.fly()i1 = Insect(6)i1.fly()

14.多态

面向对象的三大特征: 封装,继承,多态
多态:一种事物的多种形态,子类可以认为是父类的不同形态的实现

python是弱类型语言,声明变量时,不要求数据类型,根据赋值的类型去确定该变量的类型。c,Java强类型语言,声明变量时,已经确定该变量的数据类型,如果赋值的类型与声明的类型不一致,程序会报错。在强类型语言中:子类对象可以强转为父类类型的对象,但父类类型的对象不能强转为子类类型的对象。在强类型语言中:子类对象可以强转为父类类型的对象,父类类型的对象也能强转为子类类型的对象。

class Animal():    def __init__(self, name):        self.name = name    def eat(self):        print(self.name + "eat")class Cat(Animal):    def __init__(self, name):        Animal.__init__(self, name)    def run(self):        print(self.name + "run")class Dog(Animal):    def __init__(self, name):        Animal.__init__(self, name)class Person():    # def feedAnimalCat(self, cat):    #     print("人喂了" + cat.name)    # def feedAnimalDog(self, dog):    #     print("人喂了" + dog.name)    def feedAnimal(self, animal):        print("人喂了" + animal.name)per = Person()cat1 = Cat('喵')# per.feedAnimalCat(cat1)dog1 = Dog("汪")# per.feedAnimalDog(dog1)per.feedAnimal(cat1)per.feedAnimal(dog1)
class Animal(object):    def run(self):        print('animal is running')class Dog(object):    def run(self):        print('dog is running')class Cat(object):    def run(self):        print('cat is running')def run_twice(animal):    animal.run()    animal.run()run_twice(Animal())run_twice(Cat())run_twice(Dog())class Tortoise(Animal):    def run(self):        print('Tortoise is running slowly...')run_twice(Tortoise())

转载地址:http://cqgxo.baihongyu.com/

你可能感兴趣的文章
java学习笔记 --- String类
查看>>
1.5-cut命令
查看>>
我的友情链接
查看>>
从技术角度看人与人的沟通
查看>>
加速sshd
查看>>
15.3、SElinux介绍
查看>>
关于Nagios Core
查看>>
python基本数据类型的介绍
查看>>
原生的js写Ajax请求
查看>>
战略合作背后的秘密:VMware沦为AWS的渠道商?
查看>>
tar.gz安装
查看>>
Centos6.5 glibc 升级
查看>>
排序——C++函数调用
查看>>
Pandownload关了,还有更牛逼的百度网盘全速下载方法
查看>>
【转】C++文件流の添加数字到指定文件中
查看>>
在网络设备上暂挂会话
查看>>
SQL中访问远程数据库(MSSQL)
查看>>
Django学习
查看>>
python excel操作
查看>>
我的友情链接
查看>>