对象-7/18

什么是对象?

对象是内存中专门用来存储数据的一块区域。

对象中可以存放各种数据(比如:数字、布尔值、代码)

对象由三部分组成:

1. 对象的标示(id)

2. 对象的类型(type)

3. 对象的值(value)

  面对对象   

-python是一门面对对象的编程语言

-所谓面向对象的语言,简单理解就是语言中的所有操作都是通过对象来进行的

-面向过程的编程语言

  指将我们程序的逻辑分成一个一个的步骤,通过对每个步骤的抽象来完成程序

-面向过程的编程思想将一个功能分解为一个一个小的步骤,我们通过完成一个一个小的步骤来完成一个程序

-这种编程思路符合人类思维,编写起来相对比较简单,但是这种方式编写代码往往只适用于一个功能,即使功能相差极小,也往往需要重新编写代码,所以她的可复用性比较低,并且难于维护

-面向对象的编程语言

-面向对象的编程语言,关注的是对象,而不关注于过程

eg:孩她妈起床叫孩子上学

类(class)

我们目前所学习的对象都是python内置的对象

但是内置对象不能满足所有需求,所以我们在开发中经常需要定义一些对象

类,简单理解它就相当于一个图纸,在程序中我们需要根据类来创建对象

类就是对象的图纸

-我们也称对象是类的实例(instance)

-如果多个对象是通过一个类创建的,我们称这些对象都是一类对象

-像:int() float() bool() str() list() dict().....这些都是类

a=int(10) 创建一个int

定义一个简单的类

使用class关键字来定义类,语法和函数很像

class 类名([父类]):

        代码块

类,也是一个对象,是一个用来创建对象的对象

类是type类型的对象,定义类实际上就是定义了一个type类型的对象

-使用类创建对象的流程

1.创建一个变量mc

2.在内存中创建一个新对象

3.将对象的id赋值给变量

#定义类必须用大驼峰命名法
class MyClass():
    pass
#使用MyClass创建一个对象
#使用类来创建一个对象,就像调用一个函数一样
mc=MyClass()
print(type(mc))
#mc就是通过MyClass创建的对象,mc是MyClass的实例
#isinstance()用来检查一个对象是否是一个类的实例
r=isinstance(mc,MyClass)
print(r)
print(id(MyClass),type(MyClass))
#类也是一个对象
#现在我们通过MyClass这个类创建的对象都是一个空对象
#也就是对象实际上什么都没有,就相当于一个空盒子
#可以向对象中添加变量,对象中的变量称为属性
#语法:对象.属性名=属性值
mc.name='js'
print(mc.name)
ma=MyClass()
print(ma,mc)

类的定义

-类和对象都是对现实生活的事物或程序中的内容的抽象

-实际上所有的事物都是由两部分构成:

1,数据(属性)

2. 行为(方法) 

1.   在类的代码块中我们可以定义变量和函数,变量会成为该类实例都可以通过     对象.属性名。   的方式访问

2.   函数会成为该类实例的公共方法,所有该类实例都可以通过。     对象.方法名()的形式调用方法

注意:

方法调用时,第一个参数由解析器自动传递,所以定义方法时要至少定义一个形参

class Person():
    #在类的代码块中,我们可以定义变量和函数
    #在类中我们定义的变量,将会称为所有实例的公共属性
    #所有实例都可以访问这些变量
    high=170
    name='js'
    def fn(a):
        print('hello')
#创建person的实例
p1=Person()
p2=Person()
#调用方法,对象.方法名()
#如果是函数调用,则调用时传几个参数,就会有几个实参
#但如果是方法调用,默认传递一个参数,所以方法中至少要定义一个形参
p2.fn()

实例为什么可以访问到类中的属性和方法?

  类中定义的属性和方法都是公共的,任何该类实例都可以

 - 属性和方法查找的流程

        当我们调用一个对象的属性时,解析器会先在当前对象中寻找是否含有该属性,如果有则直接返回当前对象的属性值

如果没有,则去当前对象的类对象中去寻找

-类对象和实例对象中都可以保存属性(方法)

        -如果这个属性(方法)是所有的实例共享的,则应该将其保存到类对象中

        ​​​​​​​-如果这个属性(方法)是某个实例独有,则应该保存到实例对象中

-一般情况下,属性保存到实例对象中

-方法保存到类对象中

class Person():
    name='js'
    def fn(self):
        print('hello我是%s'% self.name)
       
p1=Person()
p2=Person()
p1.name='js'
p2.name='ky'
p2.fn()
print(p2)
#方法每次被调用时,解析器都会自动传递第一个实参
#p1调的,则第一个参数就是p1对象
#p2调的,则第一个参数就是p2对象

类的特殊方法init

目前来说,对于person类来说name是必须的,我们希望在创建对象时必须设置name属性,如果不设置对象将无法创建,而且属性的创建是自动完成的,而不是在创建对象以后手动完成的!

class Person():
    #特殊方法不需要自己调用,不要尝试去调用特殊方法
    #学习特殊方法:
    #   1.特殊方法什么时候调用
    #   2.特殊方法有什么用
    #创建对象的流程
    #   1.创建一个变量
    #   2.在内存中创建一个新对象
    #   3._执行类代码块中的代码(只在类定义的时候执行一次)
    #   4.__init__(self)方法执行
    #   5.将对象id赋值给变量


    #init会在对象创建以后立刻执行
    #init可以用来向新创建的对象中初始化属性
    #调用类创建对象时,类否遍的所有参数会依次传递到init()中
    def __init__(self,name):
        self.name=name
        #通过self向新建的对象中初始化属性
    name='js'
    def fn(self):
        print('hello我是%s'% self.name)
       
p1=Person('jess')
p2=Person('kyle')

p1.fn()
p2.fn()

创建对象的流程:

p1=Person()的运行流程

 1.创建一个变量
    #   2.在内存中创建一个新对象
    #   3._执行类代码块中的代码(只在类定义的时候执行一次)
    #   4.__init__(self)方法执行
    #   5.将对象id赋值给变量

类的基本结构:

class类名([父类]):
    公共属性... ...
   
    #对象的初始化方法
    def__init__(self,...):
        ... ...
    
    #其他的方法
    def method_1(self,...):
        ... ...
    def method_1(self,...):
        ... ...

练习:

#练习:
#尝试定义一个表示狗的类(Dog)
#属性:
#name
#age
#gender
#height
#方法:
#jiao()
#yao()
#run()
class Dog():
    def __init__(self,name,age,gender):
        self.name=name
        self.age=age
        self.gender=gender
    def yao(self):
        print('%s咬我了'%self.name)
    def jiao(self):
        print('%s在叫'%self.name)
    def run(self):
        print('%s的%s在跑'%(self.age,self.name))
n1=Dog('八月','1岁','boy')
n2=Dog('pipi','6个月','girl')
n1.yao()
n1.jiao()
n1.run()
n2.yao()
n2.jiao()
n2.run()

封装:是面向对象的三大特征

   封装指的是隐藏对象中一些不希望被外部锁访问到的属性或方法

1. 如何隐藏一个对象中的属性?

                -将对象的属性名,修改为一个外部不知道的名字

2. 如何获取(修改)对象中的属性?

                -需要提供一个getter和setter方法使外部可以访问到属性

                -getter获取对象中的指定属性(get_属性名)

                -setter用来设置对象的指定属性(get_属性名)

使用封装增加了类的定义的复杂程度,但他也确保了数据的安全性

        ​​​​​​​1. 隐藏了属性名,使调用者无法随意的修改对象中的属性

        2.增加了getter和setter方法,很好的控制属性是否是只读的

        ​​​​​​​        如果希望属性是只读的,则可以直接去掉setter方法

        ​​​​​​​        ​​​​​​​如果希望属性不能被外部访问,则可以直接去掉getter方法

        ​​3.使用setter方法设置属性,可以增加数据的验证,确保数据的值是正确的

        4.使用getter方法获取属性,使用setter方法设置属性

        ​​​​​​​        可以在读取属性和修改属性的同时做一些其他处理

class Dog():
    def __init__(self,name):
        self.hidden_name=name
    def yao(self):
        print('%s咬我了'%self.hidden_name)
    def get_name(self):
        return self.hidden_name
    def set_name(self,name):
        self.hidden_name=name
n1=Dog('八月')
print(n1.get_name())
n1.set_name('77')
print(n1.get_name())

隐藏类中的属性

一般使用_的属性都是私有属性,没有特殊需求不要修改私有属性


#可以为对象的属性使用双下划线开头<__xxx
#双下划线开头的属性,是对象的隐藏属性,隐藏属性只能在类的内部访问无法通过对象访问
#其实隐藏属性只不过是python自动为属性改了一个名字,eg:__name    ->    _类名__name
class Dog():
    def __init__(self,name):
        self.__name=name
    def yao(self):
        print('%s咬我了'%self.hidden_name)
    def get_name(self):
        return self.__name
    def set_name(self,name):
        self.__name=name
n1=Dog('八月')
print(n1.get_name())
n1.set_name('77')
print(n1.get_name())


#使用__开头的属性,实际上依然可以在外部访问,所以这种方式我们一般不用
#一般我们会将一些私有属性(不希望被外部访问的属性)以_开头
class Dog():
    def __init__(self,name):
        self._name=name
    def yao(self):
        print('%s咬我了'%self.hidden_name)
    def get_name(self):
        return self._name
    def set_name(self,name):
        self._name=name
n1=Dog('八月')
print(n1.get_name())
n1.set_name('77')
print(n1.get_name())

property装饰器

property装饰器,用来将一个get方法转换为对象的属性

添加property装饰器以后我们就可以像调用属性一样使用get方法

使用property装饰的方法,必须和属性名是一样的

setter方法的装饰器:@属性名.setter

class Dog():
    def __init__(self,name):
        self._name=name
    def yao(self):
        print('%s咬我了'%self.hidden_name)
    @property
    def name(self):
        print('get函数')
        return self._name
    @name.setter
    def name(self,name):
        print('set函数')
        self._name=name
n1=Dog('八月')
#直接打印属性名,不需要调用函数
print(n1.name)
n1.name='77'
print(n1.name)

继承

有一个类,能够实现我们需要的大部分功能,但是不能实现全部功能

如何能让这个类来实现全部的功能呢?

        1.直接修改这个类,在这个类中添加我们需要的功能

        ​​​​​​​        - 修改起来会比较麻烦,并且会违反ocp原则

        2.直接创建一个新的类

        ​​​​​​​        -创建一个新的类比较麻烦,并且需要大量的进行复制粘贴,胡出现大量的重复性代码

        3.直接从Animal类中来继承他的属性和方法

        ​​​​​​​        -继承是面向对象的三大特征之一

        ​​​​​​​        -通过继承我们可以使一个类获取到其他类中的属性和方法

        ​​​​​​​        -定义类时,可以在类名后的括号中指定当前类的父类(超类、基类、super)子类(衍生类)可以直接继承父类中的所有属性和方法

#定义一个 Animal 中需要两个方法:run() bark()
#又定义了Dog 中需要三种方法:run() bark() yao()
class Animal():
    def run(self):
        print('它在跑')
    def bark(self):
        print('汪汪汪')
#Animal是 Dog的父类
class Dog(Animal):
    def yao(self):
        print('%s咬我了'%self.name)
class 柯基(Dog):
    def sleep(self):
        print('%s睡着了'%self.name)
n1=Dog()
n1.name='88'
n1.run()
n2=柯基()
n2.name='11'
n2.sleep()

#判断是不是该类的实例
print(isinstance(n1,Animal))
print(isinstance(n2,Animal))
#判断一个类是不是另一个类的子类
print(issubclass(Dog,Animal))
print(issubclass(柯基,Animal))


print(issubclass(柯基,object))

在创建类时,如果省略了负累,则默认父类为object

object是所有类的父类,所有类都继承自object

如果在子类中如果有和父类同名的方法,则通过子类实例去调用方法时,会调用子类方法而不是父类的方法,这个特点我们称为叫做方法的重写(覆盖,override)

当我们调用一个对象的方法时,会优先去当前对象中寻找是否具有该方法,如果有则直接调用,如果没有,则去当前对象的父类中寻找,以此类推,直到找到object,如果依然没有找到则会报错

class Animal():
    def run(self):
        print('它在跑')
    def bark(self):
        print('汪汪汪')
class Dog(Animal):
    def bark(self):
        print('他在汪汪的叫')

n1=Dog()
n1.name='88'
n1.bark()

父类中的所有方法都会被子类继承,包括特殊方法“__init__”也可以重写特殊方法

super()可以用来获取当前类的父类

class Animal():
    def __init__(self,name,age):
        self._name=name
        self._age=age
    def run(self):
        print('它在跑')
    def bark(self):
        print('汪汪汪')
class 柯基(Animal):
    def __init__(self,name,age,gender):

        #希望可以直接调用父类的__init__来初始化父类中定义的属性
        #super()可以用来获取当前类的父类
        #并且通过super()返回对象调用父类方法时,不需要传递self
        super().__init__(name,age)
        self._gender=gender
    def bark(self):
        print('他在汪汪的叫')

n1=柯基('88','9','male')
n1.name='88'
n1.bark()

类名.__bases__  这个属性可以用来获取当前类的所有父类

class A(object):
    def test1(self):
        print('aaa')
class B(object):
    def test2(self):
        print('bbb')

#python中是支持多重继承的,也就是我们可以为一个类同时指定多个父类
#可以在类名()后边添加多个类,来实现多重继承
#多重继承,会使子类同时拥有多个父类,并且会获取到所有父类中的方法
#在开发中没有特殊情况,应该尽量避免使用多重继承,因为多重继承会让我们的代码过#于复杂
class C(A,B):
    def test3(self):
        print('ccc')

print(A.__bases__)
print(C.__bases__)

如果多个父类中有同名的方法,则会先在第一个父类中寻找,然后找第二个,然后找第三个...  ...  前边父类的方法会覆盖后边父类的方法

多态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值