面向对象

1.面向对象的概念

  • 1.1python是一门面向对象的编程语言
    • 面向对象就是指所有的操作都是通过对象来进行的
    • 面向过程,就是把事件分为诺干步骤,通过对每个步骤的抽象来完成程序,其优点是符合人类的逻辑思维,易于编写,而往往适用单个任务,多种任务代码复用率低。
  • 1.2面向对象关注的是对象,不关注过程,将所以的功能统一保存到对象中,要使用功能就去找相关的对象。其优点是易于阅读,方便维护,容易复用,但编写不符合正常的逻辑思维,相对困难。

2.类(Class)

  • 2.1python中内置对象int()、str()、list()等,有时我们要在python中建立自定义的对象,这时候我们就要用到类。
    • 通过Jerry老师的讲解,我理解类就是在python中定义了一种新的数据类型,所以通过我们自定义类实例化的对象,都属于这个类型。
    char = 'I love learning python!'
    class MyClass:
        pass
    mc = MyClass()
    mc.name = 'Tom'
    print(id(str),type(str),str)#1853144624 <class 'type'> <class 'str'>
    print(id(char),type(char),char) #73204128 <class 'str'> I love learning python!
    print(id(MyClass),type(MyClass),MyClass)#97961864 <class 'type'> <class '__main__.MyClass'>
    print(id(mc),type(mc),mc)#4318952 <class '__main__.MyClass'> <__main__.MyClass object at 0x0041E6E8>
    
    • 通过上面的例子可以充分说明我们建立的类和str都是一个class 'type'的类型,而它们的实例都是以它们为类型。变量char的类型为class 'str',而变量mc的类型为class 'main.MyClass'。
    • isinstance()以前用来判断输入是否是整数isinstance(a,int),实际上它是用来判断对象a是不是int类的实例,所以要判断一个对象是不是类的实例就用isinstance。
    a = 1
    class MyClass():
        pass
    mc = MyClass() 
    mc2 = MyClass()
    mc3 = MyClass()
    mc4 = MyClass()
    # isinstance() 用来检测一个对象是否是一个类的实例 返回值是布尔类型  
    isinstance(a,int)#Ture
    isinstance(mc3,MyClass)#Ture
    isinstance(a,MyClass)#False
    
  • 2.2类的语法
    class 类名([父类]):
      代码块
    
  • 2.3类的定义
    • 类和对象都是对现实生活中事物的抽象
    • 事物(对象)一般包含数据(属性)和行为(方法)。
    • 在类的代码块中一般定义变量和函数,变量会成为该类实例的公共属性,所有实例都可以通过实例名.属性名来访问;函数会成为该类实例的公共方法,所有实例都可以通过实例名.方法名()来访问。
class Students():
    def __init__(self,name,age):
        '''
        :param name: 姓名
        :param age: 年龄
        :param curriculum:学习课程,默认为空字符
        '''
        self.name = name
        self.age = age
        self.curriculum = ''
    def choose_curriculum(self,*args):
        '''
        记录学生选的课程
        :param args: 可以输入一个或者多个课程名
        :return: 课程字符串self.curriculum
        '''
        for course in args:
            if self.curriculum == '':
                self.curriculum = course
            else:
                self.curriculum += f'、{course}'
        return self.curriculum
def show_information():
    '''
    打印学生信息
    '''
    s1 = Students('郭靖',28)
    s1.choose_curriculum('降龙十八掌','九阴真经')
    s2 = Students('张无忌',16)
    s2.choose_curriculum('九阳神功')
    print(f'姓名:{s1.name},年龄:{s1.age},学习科目:{s1.curriculum}。')
    print(f'姓名:{s2.name},年龄:{s2.age},学习科目:{s2.curriculum}。')
if __name__ == "__main__":
    show_information()

3.参数self

  • 3.1属性和方法
    • 类中的属性和方法都是公共的,任务该类的实例都可以访问。
    • 实例中的属性和方法查找流程,先从实例中查找,如果有则直接返回结果,如果在实例中查找不到时,再查找该实例的类中公共的属性或方法,如果有则返回公共属性或方法,如果还找不到,报错。
    • 实例和类中都可以保存属性和方法,公共的属性和方法放在类里,独特的属性和方法放在实例中,一般情况方法放在类中,属性放在实例中。
  • 3.2self参数
    • 在调用方法时,解释器会自动为方法传递实例给方法的第一个位置参数,因此,在定义方法时,必须要多定义一个位置形参来接收实例,一般情况下我们定义这个形参为self。
    • self总是指调用时类的实例。
class A:
    n = 8
    def n_factorial(a):
        r = 1
        temp = a.n
        while temp > 0:
            r *= temp
            temp -= 1
        print(f'{a.n}的阶乘为{r}')
a = A()
a.n_factorial() #运行结果为8的阶乘为40320

4.特殊方法

  • 4.1__init__()方法就是一个特殊方法,调用时机是实例化类时调用此方法,用来定义属性。我的理解是可以用参数传递的方式使我们的每个实例对象的属性个性化。
  • 4.2类的特殊方法的学习方法。
    • 在什么时机调用特殊方法。
    • 了解特殊方法的作用。
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
p = Person('Tom',23)
print(p.name,p.age) #Tom 23
p.name = 'jack'
print(p.name,p.age) #jack 23

5.封装

  • 5.1封装的原因
    为了数据更安全,主要的是联合开发时告诉同事哪些属性可以变,哪些属性不会变。
  • 5.2封装的方法,隐藏属性名,通过getter()和setter()两个方法来获取和修改属性。
    • getter()是获取对象中指定的属性
    • setter()是用来设置对象中指定的属性
    • 属性名,是隐藏属性,实际上是系统改名为类名属性名,我们一般不用这种方法,一般用属性名来告诉别人这个属性是私有的,不要随意更改。
class Fish():
    def __init__(self,name,color='金黄色',genre='金鱼'):
        self.hidden_name = name
        self.__color = color #隐藏属性
        self._genre = genre #一般写法

    def get_name(self):
        return self.hidden_name

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

    def get_color(self):
        return self.__color

    def set_color(self,color):
        self.__color = color

    def get_genre(self):
        return self._genre

    def set_genre(self,genre):
        self._genre = genre

    def speak(self):
        print(f'{self.__color}的{self.hidden_name}是{self._genre}')

f1 = Fish('小金')
ff1.speak() #金黄色的小金是金鱼
f1.hidden_name = '金金'
print(f1.get_name()) #金金
f1.speak() #金黄色的金金是金鱼
f1.set_name('小斑')
f1.set_color('红色')
f1.set_genre('东星斑鱼')
f1.speak() #红色的小斑是东星斑鱼
  • 5.3装饰器property
    • 将方法调用形式改为属性调用形式,这个可以来指明你查看和修改的是属性。
class Fish():
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name

    @name.deleter
    def name(self):
        del self._name

f = Fish('小金')
print(f.name)#小金
f.name = '小黑'
print(f.name)#小黑
del f.name
#print(f.name)#'Fish' object has no attribute '_name'
f.name = '小红'
print(f.name)#小红

另外一种使用方法name = property(get_name,set_name,del_name),第一种方法你的方法名必须保持一致,这样对于方法命名规则就会有所破坏,要保持命名方法的规则可以用第二种方法,当然在一般情况下单独用@property用的比较多,而setter和deleter用的比较少,所以在一般情况就用@property就可以了。

  • 5.4封装的思考
    • 封装的作用在独立开发中,可能还看不出来,相反增加了类的复杂度。但是在联合开发中封装却可以避免不必要的bug出现。
    • 封装可以在setter方法设置属性时过滤掉不希望出现的错误设置或者进行数据类型判断,同理在输出数据时也可是进行一些优化和操作。

6.继承(object)

  • 6.1继承是类的三大特性之一,它使类与类之间产生了关系,有了这个关系看,才有了多态的特性,同时提高了代码的复用性。
  • 6.2通过继承使一个类拥有其他类的属性和方法,通常便是方法,在定义类时类名后面的括号内填写父类名,例如:class B(A): pass,B是A的子类,A是B的父类或者超类,B继承了A中所以的属性和方法。所有类都是object的子类。
class A(object):
    name = '葫芦娃'
    def speak(self):
        print('我是%s,很高兴认识你!!!'%self.name)

class B(A):
    pass
b = B()
b.speak() #我是葫芦娃,很高兴认识你!!!
b.name = '钢铁侠'
b.speak() #我是钢铁侠,很高兴认识你!!!
  • 6.3方法的重写,就是在子类中含有和父类相同的方法名时,通过子类实例调用该方法时,直接调用子类的方法,不调用父类方法,这一特性叫做方法重写或覆盖。实例调用方法的顺序是先从实例化的类里找,如果没有则去父类找,如果没有则去父类的父类里找,以此类推,直到object里名都没有找到就报错。(就近原则)
class A(object):
  def speak(self):
   print('A..........')
class B(A):
  def speak(self):
   print("B.............")
class C(B):
 def speak(self):
  print("C.............")
c = C()
c.speak() #C.............
  • 6.4super()可以获取当前类的父类,通过super()返回对象调用父类方法时,不需要传递self的参数
class Animal():
    def __init__(self,name):
        self.name = name
    def run(self):
        print('%s跑起来了!!!'%self.name)
    def sleep(self):
        print('%s在睡觉!!!'%self.name)
class Dog(Animal):
    def __init__(self,name,age):
        super().__init__(name)
        self.age = age
    def eat(self):
        print('%s正在吃骨头!!!'%self.name)
    def run(self):
        print('狗在跑!!!')

d = Dog('泰迪',3)
d.eat()#泰迪正在吃骨头!!!
d.run()#狗在跑!!!
d.sleep()#泰迪在睡觉!!!
  • 6.5多重继承,一个类继承了多个类的属性和方法。python中允许多类继承,在定义类时括号内可以写多个类,如果多个父类里面有方法重名,先从第一个父类开始找,第一个没有找到再找第二个,以此类推,就是排前面的父类方法覆盖拍后面的父类方法。一般情况下要避免使用多重继续,这会使程序复杂化。
class A():
    def speak(self):
        print('A...........')
class B():
    def speak2(self):
        print('B...........')
class C(A,B):
    pass
c=C()
c.speak() #A...........
c.speak2() #B...........

7.多态

  • 7.1多态是面向对象三大特性之一,就是一个对象有多种形态去呈现。差了下百度,多态指同一操作作用与不同类的实例,将产生不同的执行结果,即不同类的对象收到相同的消息时,将得到不同的结果。
class Person:
    def __init__(self,name,age):
        self._name = name
        self.age = age

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self,name):
        self._name = name

class Pets:
    def __init__(self,name):
        self._name =name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name

class C:
    name ='超人'

p1=Person('张三',23)
p2=Pets('喵喵')
p3=C()
def speak(obj):
    print(f'大家好,我是{obj.name}。')
speak(p1)#大家好,我是张三。
speak(p2)#大家好,我是喵喵。
speak(p3)#大家好,我是超人。
  • 7.2多态我的理解就是同一件事情让不同的类去做,结果是多样的,举个不恰当的例子,就是一群动物赛跑,发令枪一响,动物们都开始跑了,鸟是用飞的,乌龟是爬的,兔子是用跳的。每个对象都用它自己的逻辑结构去完成同一件事,都得到它自己想要的结果。
    -7.3面向对象三大特性
    • 封装:保证数据的安全性。隔离设计者和使用者
    • 继承:确保了对象的扩展性。扩展时只要新类继承旧类就可以
    • 多态:保持了程序的灵活性。一个功能可以给多个对象使用。

8.类的属性和方法

  • 8.1类属性
    • 实例属性,实例可以访问,类无法访问。
    • 类属性,实例和类都可以访问。如果在实例中重新定义类属性,实例中的对应类属性改变,类属性本身没有变化。
    • 魔法方法init定义的属性是实例属性。
class A:
    name = 1
    def __init__(self):
        self.age = 26

print(A.name) #1
a = A()
print(a.name) #1
a.name = 'Marry'
print(a.name,A.name)#Marry 1
print(a.age) #26
print(A.age) #AttributeError: type object 'A' has no attribute 'age'
  • 8.2类方法
    • 类中定义的方法一般都是实例方法。
    • 类方法的定义格式,在定义前加装饰器@classmethod,同时方法中默认拥有cls形参,cls代表的是这个类。实例和类都可以调用。
    • 类的静态方法,格式一般为@staticmethod,该方法没有默认形参,不能使用该类的任何属性和方法,一般情况为工具方法,放置一些没有具体类的方法。实例和类都可以调用静态方法。
class A:
    
    def __init__(self):
        self.age = 26

    @classmethod
    def speak(cls):
        print('我是类方法',cls)

    @staticmethod
    def tools():
        #print('我是静态方法',self.name)#无法使用该类的属性和方法
        print('我是静态方法!')

a =A()
a.speak()#我是类方法 <class '__main__.A'>
A.speak()#我是类方法 <class '__main__.A'>
a.tools()#我是静态方法!
A.tools()#我是静态方法!
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342