python面向对象知识总结梳理

面向对象知识梳理、总结

什么是面向对象?

面向对象简称是OOP,是目前主流的编程思想,JavaScript本身也是面向对象的编程语言,对于动态网页行为的编程,只要稍微对它有了解就可以的。对象这个词在是从英文“object”中翻译过来的,在之前的编程过程中,我们过多的考虑的是计算机硬件的工作方式,导致编程的难度增加,经过不断的发展和改良,主流的程序语言在想人类的自然语言转变,不过编程的思想还是没有重大性的突破。

对象就是人对各种具体物体抽象之后的概念,人们每天都在跟各种各样的对象打交道,比如说一本书就是一个对象。在面向对象的编程过程中,对象有很多的特性,比如说高度、宽度、颜色等等,这些都是对象的属性,而且对象还有更多的功能,比如一部手机,可以听歌,看视频,打电话,这些可以理解成有个对象的方法,这些方法可以看成是函数,并且对象不是孤立的,它还具有对象的继承性。在编程的过程中,我们可以把所有的问题看做是对象,以人的思维解决问题。对象实际上就是一组数据的集合,并且都已经被命名,这些数据的根据就是对象的属性,可以被访问。如果想访问一个外部的对象我们就必须先引进它,好比你想用国外的东西一样,只有你从国外把它带回来你才能使用。那么下面我们就看看如何创建一个对象吧:在我们JavaScript内部有很多是内置对象,我们也可以直接创建一个新的对象,创建对象的方法就是使用new运算符和构造函数,eg:var new_name=new 构造函数;预先定义的构造函数直接直接决定所创建对象的类型,如果想创建一个空的对象,可以使用object()构造函数。还有就是定义对象的属性,其实定义对象的属性很简单,直接在对象后面用点运算符号声明属性的名称,并可直接赋值。创建对象所用的构造函数是预定义的,如Object()可以用于创建一个空对象,而创建数组对象我们可以使用Array()构造函数。这些都是些内置的构造函数,当然我们也可以自定义,就是自定义构造函数,比如你想构造有个食物的对象,就是构造food()的对象,通过向这个构造函数传递参数以初始化对象实例。不过构造函数只能初始化对象实例而不能返回对象实例,需要使用new运算符才能创建食物的对象实例。

什么是类和对象?

1)对象:对象是人们要进行研究的任何事物,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。对象具有状态,一个对象用数据值来描述它的状态。对象还有操作,用于改变对象的状态,对象及其操作就是对象的行为。对象实现了数据和操作的结合,使数据和操作封装于对象的统一体中。

2)类:具有相同特性(数据元素)和行为(功能)的对象的抽象就是类。因此,对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象,类实际上就是一种数据类型。类具有属性,它是对象的状态的抽象,用数据结构来描述类的属性。类具有操作,它是对象的行为的抽象,用操作名和实现该操作的方法来描述。

类与对象的关系就如模具和铸件的关系,类的实力化的结果就是对象,而对对象的抽象就是类,类描述了一组有相同特性(属性)和相同行为的对象。

类的声明语法和注意事项/

对象的创建语法和注意事项/

对象操作属性/

对象调用方法/

第一种方法:

class Call:
	def setName(self, name):
		self.name = name
	def kick(self):
		print("我的名字是{}".format(self.name))

call = Call()
call.setName("DaShuaige")
print(call.kick())

这种方法需要先声明一个对象,然后通过一个函数将参数传入对象中。

第二种方法:

class Ball:
	def __init__(self, name):
		self.name = name
	def kick(self):
		print("我叫{}".format(self.name))
ball = Ball("DaHaoren")
print(ball.kick())

这种方法在声明一个对象的时候考研将参数直接通过调用类导入对象当中。

类和对象的区别?

1,类是一个抽象的概念,它不存在于现实中的时间/空间里,类只是为所有的对象定义了抽象的属性与行为。就好像“Person(人)”这个类,它虽然可以包含很多个体,但它本身不存在于现实世界上。
2,对象是类的一个具体。它是一个实实在在存在的东西。
3,类是一个静态的概念,类本身不携带任何数据。当没有为类创建任何对象时,类本身不存在于内存空间中。
4,对象是一个动态的概念。每一个对象都存在着有别于其它对象的属于自己的独特的属性和行为。对象的属性可以随着它自己的行为而发生改变。

面向对象封装的意义

为了保护敏感/隐私属性数据,让外界访问当前对象中的属性数据时,可以按照我们指定的条件进行访问,否则不允许访问,提高属性数据的安全性。

封装的操作步骤

  1. 将当前类型中所有属性私有化。
  2. 给每个属性提供访问属性数据的set/get方法。
  3. 给敏感属性的访问方法中,添加访问限制条件。
class Person:
	def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def set_name(self, name):
        self.__name = name

    def get_name(self):
        return self.__name

    def set_age(self, age):
        if 18 <= age <= 40:
            self.__age = age
        else:
            print("输入年龄不合法")

    def get_age(self):
        return self.__age


# 创建用户对象
p = Person("tom", 18)
print(p.get_name(), p.get_age())

# 修改对象的属性数据
p.set_name("jerry")
p.set_age(1000)
print(p.get_name(), p.get_age())

封装时的注意事项

封装后存在的问题和解决方案

  1. 误区:什么样的属性应该封装?封装的话是不是一定要添加限制访问条件?
    (1) 为了让定义的数据类型,能使用不同的应用场景,一帮情况下我们
    要对当前类型的所有属性进行封装处理。
    (2) 封装属性之后,会提供访问属性数据的set/get方法,开发过程中方法中不需要添加
    任何限制条件,只是预留了可以添加限制条件的方法而已,后期根据项目需求进行限制
    条件的完善。
class User:
    """用户类型"""

    def __init__(self, username, password):
        self.__username = username
        self.__password = password

    def set_username(self, username):
        self.__username = username

    def get_username(self):
        return self.__username

    def set_password(self, password):
        self.__password = password

    def get_password(self):
        return self.__password
  1. 误区:私有属性,完全不能直接访问
    我们定义了私有属性,就是两个下划线开头的属性
    理论上外界不能直接访问,而是要通过我们提供的set/get方法间接访问
    功能开发过程中,代码和功能都可能会存在一些问题
    如果发现问题~一定要及时沟通,而不是私自修改。

    class Person:
    
    def __init__(self, name):
        self.__name = name
    
    p = Person("tom")
    #私有属性破坏性访问方式:我们自己要知道,但是严禁使用
    p._Person__name = "jerry"
    print(p._Person__name)
    
    
  2. 误区:关于对象属性的扩展

class Goods:

    def __init__(self, name, price):
        self.__name = name
        self.__price = price

    def set_name(self, name):
        self.__name = name

    def get_name(self):
        return self.__name

    def set_price(self, price):
        self.__price = price

    def get_price(self):
        return self.__price


car = Goods("奥拓", 18000)
print("car的价格:", car.get_price())

# 如果通过 对象的引用变量.属性 直接赋值,该属性又不是类型中定义的属性
# 这个属性就是 单独属于这个对象 的扩展属性。
car.__price = 20000
print("car的价格", car.__price, "---", car.get_price())

# 扩展属性,属于对象car
car.__color = "红色"
print(car.__color)

# car2 = Goods("奥迪", 300000)
# print(car2.__color)

"""
但是,这样的扩展方式,破坏了原有的封装语法,让代码的可读性出现了严重的下降

解决方案:在类型中,定义好~该对象可以出现的属性,其他任何扩展属性就不能添加了。
"""
class Pet:
    """宠物类型:限制该类型只能出现哪些属性"""
    # 限制该类型的对象,只能拥有下面列表中出现的属性
    __slots__ = ['__name', '__age', '__gender', 'color']

    def __init__(self, name, age, gender):
        self.__name = name
        self.__age = age
        self.__gender = gender

    def set_name(self, name):
        self.__name = name

    def get_name(self):
        return self.__name

    def set_age(self, age):
        self.__age = age

    def get_age(self):
        return self.__age

    def set_gender(self, gender):
        self.__gender = gender

    def get_gender(self):
        return self.__gender

p = Pet("tomcat", 18, "公")
print(p.get_name(), p.get_age(), p.get_gender())
# 扩展属性
p.color = "灰色"
print(p.get_name(), p.get_age(), p.get_gender(), p.color)

p.email = "[email protected]"
print(p.email)

面向对象继承的意义【代码冗余、功能扩展】

概念:继承是指在已存在的类的基础上扩展产生新的类。已存在的类称为基类(或父类、超类),新产生的类称为子类(或派生类)。

意义:继承是面向对象程序设计的三大特征(封装、继承和多态)之一,不具有继承功能的语言不能称之为面向对象程序设计语言(如VB),继承具有如下特点: 继承划分了类的层次性,父类代表的是更一般、更泛化的类,而子类则是更为具体、更为细化; 继承是实现代码重用、扩展软件功能的重要手段,子类中与父类完全相同的属性和方法不必重写,只需写出新增或改写的内容,这就是说子类可以复用父类的内容,不必一切从零开始。

继承的基本语法

继承基本语法
体现的是,某个小类型,属于某个大类型的
如:男人 是 人 的一种类型
生活中:约定
代码中:约定 Man类型就是Person类型 非强制
代码中:强制约束:通过继承关系,体现某个类型属于另一个类型

关于继承:
python中的所有类型,都是直接或者间接继承自object类型的
object:对象 万物皆对象
python3中类型声明语法:
class 类型名称: # 隐式继承object类型
pass
class 类型名称(object): # 显式继承object类型
pass
python2中类型的声明语法:
class 类型名称: # 经典类
pass
class 类型名称(object): # 新式类
pass

继承的语法:
class 类型名称(要继承的类型):
pass

继承的特性:
代码中出现了继承,类型就出现了新的名称:
被继承的类型:父类
当前类型:子类
体现的是:子类继承父类
子类中就可以继承父类中的属性和方法【公共】
子类中可以直接使用父类的属性和方法

class Person:
    """人的类型"""

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


class Man(Person):
    """男人"""
    pass


tianqi = Man("jerry")
mingxin = Man("jerry")
da_sheng = tianqi
print(type(tianqi))
# 运算符:类型判断运算符 isinstance
print(isinstance(tianqi, Man))
print(isinstance(tianqi, Person))

# 运算符:对象判断运算符 is
print(tianqi is Man)
print(tianqi is Person)
print(tianqi is mingxin)

print(tianqi is da_sheng)
print(tianqi == da_sheng)

继承的操作步骤

'''
子类对象使用父类数据
'''
class Person:

    def __init__(self, name, age, gender):
        self.name = name
        self._age = age
        self.__gender = gender

    def say(self):
        print(self.name, "滚去学习")

    def _play(self):
        print(self.name, "滚去玩")

    def __sleep(self):
        print(self.name, "嗨什么嗨,滚去睡觉")


class Child(Person):
    pass


c = Child("jerry", 18, "男")
print(c.name)# 对象访问父类中的属性
print(c._age)# 对象访问父类中的属性
# print(c.__gender)# 对象访问父类中的私有属性:ERROR
c.say()# 对象访问父类中的方法
c._play()# 对象访问父类中的方法
# c.__sleep()# 对象访问父类中的私有方法:ERROR

继承中的方法重写什么意思?怎么操作?

'''
子类类型使用父类数据

    1. 子类中访问父类的方法
        super().方法名称()
        注意:访问属性时~可能会出错。扩展~为什么会出错?

    2. 子类的__init__()方法
        如果子类中不写__init__()方法,直接使用父类的__init__()方法初始化数据
        怎么访问:如果子类中写了自己的__init__()方法,一定要调用执行父类的__init__()方法

        什么时候访问:什么时候子类写自己的__init__()方法,子类中出现独立属性时!
        为什么要访问:?

    3. 子类中可以重新定义从父类中继承的方法【方法名称和方法参数一致】:方法重写
        方法重写:子类中重写父类中已经存在的方法
            在执行过程中~如果子类中重写了方法,执行子类的方法,如果没有重写则执行父类中的方法【运行过程中的多种状态切换:运行时多态】

    在继承关系中,python中有两种事物的存在:
        数据类型-> 所有的类型,都是直接继承自type类型的
        对象-> 所有对象都是直接或者间接继承自object对象的

        python中所有的数据,都是直接或者间接继承自type类型的。

        重点:区分类型和对象的区别
'''
class Person:

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

    def say(self):
        print(self.name, "滚去学习")

    def play(self):
        print(self.name, "出门打麻将")

    def sleep(self):
        print(self.name, "嗨什么嗨,滚去睡觉")


class Child(Person):

    def __init__(self, name, age, gender, email, phone):
        super().__init__(name, age, gender)
        self.email = email
        self.phone = phone

    def speek(self):
        """子类的方法"""
        # 访问父类的属性和方法
        # print("子类speek中访问父类的属性:", super().name)
        super().say()
        print("子类的speek方法执行中......")

    def play(self):
        print(self.name, "搭积木.........")



c = Child("tom", 18, "男", "[email protected]", "15682808270")
c.speek()
print(c.email)
c.play()

p = Person("jerry", 20, "女")
p.play()
# print(p.email)

继承时从父类中默认继承了什么方法?

"""
既然出现了继承,python中的所有对象都是直接或者间接继承object
    1.我们都继承了什么?
 构造方法
    __new__  创建对象的方法   一般不使用~直接通过父类创建对象即可。
    __init__ 初始化数据的方法  一般会重写该方法,用来初始化对象数据

    __slots__ 封装时,限制属性的

    __str__ 对象字符打印方式;默认情况打印内存中16进制表示的位置
    __repr__ 交互模式中,字符打印方式

    __hash__ 获取兑现的hash数据,用于判断的依据
    __ne__ 不等于:not equals;两个对象使用!=判断的
    __ge__ 大于等于:grant or equals  判断 >=
    __gt__ 大于: grant than判断 >
    __le__ 小于等于:less or equals 判断 <=
    __lt__ 小于 less than 判断 <
    __eq__ 判断等于 equals 判断 ==

    __dict__ 将对象转换成字典
    __doc__ 说明文档
    __class__ 类型,类似于type

    __format__
    __getattribute__
    __delattr__
    __sizeof__
    __reduce__
    __reduce_ex__
    __dir__
    ____init_subclass__
    __module__

    __setattr__  给属性设置数据-一般不重写
   

双下划綫开头和结尾的方法:类型的魔法方法

 2. 这些继承的东西有什么作用?

"""
class Person:
    """人的类型"""
    def __init__(self, name, age):
        """
        人的类型初始化函数
        :param name: 初始化的姓名
        :param age: 初始化的年龄
        """
        self.name = name
        self.age = age

    def __str__(self):
        return f"人:[name:{self.name}, age:{self.age}]"

    def __hash__(self):
        return self.name.__hash__()

    def __eq__(self, other):
        # 判断两个对象~是否相等,按照业务逻辑 姓名和年龄一样,表示是同一个人
        if self.name == other.name and self.age == other.age:
            return True
        return False

    def __gt__(self, other):
        # 判断两人的大小:业务判断~按照年龄判断
        if self.age > other.age:
            return True
        return False

    def __ge__(self, other):
        if self.age >= other.age:
            return True
        return False

    def sleep(self, area):
        """
        睡觉了
        :param area 这是一个方法的参数说明
        """


# 创建对象
p1 = Person("tom", 18)
# 打印对象 0x000001E265E7ADA0~ 内存中的地址 16进制字符表示方式
print(p1) # <__main__.Person object at 0x000001E265E7ADA0>

p2 = Person("tom", 18)

print(p1 == p2)
print(p1 > p2)
print(p1 >= p2)

print(p1.__dict__)

print(p1.__doc__)
print(p1.sleep.__doc__)

python中的多继承操作语法

"""
python中的多继承
    体现的是什么样的编程思想:一个对象在不同场景中,可能扮演不同的角色【设计时多态】
"""
class Son:

    def xiao_shun(self):
        print("百善孝为先")


class Student:

    def xue_xi(self):
        print("好好学习,天天向上")


class Friend:

    def play(self):
        print("吃喝玩乐.....")


class Person(Son, Student, Friend):
    """人的类型:继承儿子、学生、朋友"""
    pass


p = Person()
# 家庭环境
if isinstance(p, Son):
    p.xiao_shun()

# 学习环境中
if isinstance(p, Student):
    p.xue_xi()

# 朋友
if isinstance(p, Friend):
    p.play()


def xue_tang(person):
    # 作为一个学员,在教室要好好学习
    if isinstance(person, Student):
        # person.play()
        person.xue_xi()


xue_tang(p)

多继承的意义

python中的多继承
体现的是什么样的编程思想:一个对象在不同场景中,可能扮演不同的角色【设计时多态】

多继承的方法查询顺序【python3 | python2经典类】

问题:如果不同的父类出现了相同名称的属性或者方法
子类会继承谁的属性或者方法?

python3中都是新式类:广度优先,从父类中查询对应的方法,查询到第一个满足的方法之后就直接返回

                object
                |
                A(object)
                |
    A_1(A) --> A_2(A)
    |
    Test(A_1, A_2)

python2中的经典类:深度优先
            A
            |
    A  --> A_2(A)
    |
    A_1(A)
    |
    Test(A_1, A_2)

class A:

    def test(self):
        print("aaaaaaaaaaaaaaaaa")


class A_1(A):

    def test(self):
        print("1111111111111111111")


class A_2(A):

    def test(self):
        print("2222222222222222222")


class Test(A_1, A_2):
    pass


t = Test()
t.test() # 1111111111111111111
# [, , , , ]
print(Test.mro())

总结两种多态的实现方式:

运行时多态

方法重写实现运行时多态,对象在执行具体的方法时,会直接执行父类中继承的对应的方法,如果该方法在子类中重写了,就会执行子类中重写过的方法,实现的是一种运行过程中的多态处理

# 定义父类
class Person(object):
    def __init__(self, name):
        self.__name = name
    def playing(self):
        print(self.__name + "正在游戏中...")
# 定义子类,继承自Person
class Man(Person):
    def __init__(self, name):
        Person.__init__(self, name)
# 定义子类,继承自Person
class Women(Person):
    def __init__(self, name):
        Person.__init__(self, name)
    def playing(self):
        print(self.__name + "正在游戏封装找茬中...")
# 创建对象
man = Man("tom")
women = Women("jerry")

man.playing()    # 子类中没有重写,直接执行从父类继承的playing()函数
women.playing() #子类中重写了,直接执行子类中的playing()函数
设计时多态

python中的多继承
一个对象在不同场景中,可能扮演不同的角色

class Son:

    def xiao_shun(self):
        print("百善孝为先")


class Student:

    def xue_xi(self):
        print("好好学习,天天向上")


class Friend:

    def play(self):
        print("吃喝玩乐.....")


class Person(Son, Student, Friend):
    """人的类型:继承儿子、学生、朋友"""
    pass


p = Person()
# 家庭环境
if isinstance(p, Son):
    p.xiao_shun()

# 学习环境中
if isinstance(p, Student):
    p.xue_xi()

# 朋友
if isinstance(p, Friend):
    p.play()


def xue_tang(person):
    # 作为一个学员,在教室要好好学习
    if isinstance(person, Student):
        # person.play()
        person.xue_xi()


xue_tang(p)

多态~和封装以及继承不同的是,没有固定的语法,没有固定的思路,只有操作的方式。从项目中体现。

你可能感兴趣的:(python面向对象知识总结梳理)