【知识点】Python进阶-2

Python进阶–2

面向对象–基础

  • 引入理解

https://blog.csdn.net/shenzixincaiji/article/details/83576687

类、对象、属性、方法
  • 基础
class student:					# 类
    age = 18					# 类的属性
    tall = 175
    phone = 'huawei'

    def sleep(self):			# 类的方法
        print('正在睡觉')

# basic												# 对象lily和对象Tom继承student类,两者的数据id一致
lily = student()
print(lily.age, lily.tall, lily.phone)		
print('lily.age的id:', id(lily.age))			  
lily.sleep()								   

Tom = student()
print(Tom.age, Tom.tall, Tom.phone)
print('Tom.age的id:', id(Tom.age))
Tom.sleep()

print('----------------------------------------')
# change 类
student.age = 20									# 第一次改变类属性,两个对象的属性也一起改变
print(lily.age, Tom.age)							# 即对两个对象都有影响
print(id(lily.age), id(Tom.age))
print('----------------------------------------')

# change 对象lily
lily.age = 19										# 改变对象lily的属性(对象属性),创建了动态的对象属性与起绑定
print(lily.age, Tom.age)							# 改变的结果不影响另一个对象的属性
print(id(lily.age), id(Tom.age))
print('----------------------------------------')
# change 类		
student.age = 21								# 再次改变类属性,lily的属性已经不受影响,Tom的属性仍会受到影响
print(lily.age, Tom.age)
print(id(lily.age), id(Tom.age))

【知识点】Python进阶-2_第1张图片

  • 高级一点
class student:
    tall = 'None'                           # 类属性,其变化同于基础部分的讲解
    def __init__(self):                     # 魔术方法
        self.name = 'None'                  # 对象属性,应用到具体对象都会给定一个初始值,可根据具体需要再做修改
        self.age = 'None'
        self.phone = 'None'

    def sleep(self):
        print('{}正在睡觉'.format(self.name))	# self就相当于具体的对象

# basic
lily = student()
print(lily.age, lily.name, lily.phone)
print('lily.age的id:', id(lily.age))
lily.sleep()									# self.name == lily.name

Tom = student()
print(Tom.age, Tom.name, Tom.phone)
print('Tom.age的id:', id(Tom.age))
Tom.sleep()										# self.name == Tom.name

print('----------------------------------')
# 初始化后的具体赋值
lily.name = 'lily'
lily.age = '15'
lily.phone = 'huawei'
print(lily.age, lily.name, lily.phone)
print('lily.age的id:', id(lily.age))
lily.sleep()

print('----------------------------------')
Tom.name = 'Tom'
Tom.age = '15'
Tom.phone = 'iphone'
print(Tom.age, Tom.name, Tom.phone)
print('Tom.age的id:', id(Tom.age))
Tom.sleep()

【知识点】Python进阶-2_第2张图片

  • 总结

类属性

使用同一类创建不同的对象

  • 若没有改变过类属性,可以通过类属性改变,来改变对象中对应类属性的值。一起改变
  • 若某一对象更改了类属性的值,则建立动态对象绑定,此对象中类属性变为修改后的数值;其他对象的类属性不变
  • 再次改变类属性,已经动态绑定的对象,其对象的类属性不会受到影响;对于没有“私自”更改类属性的对象,其对应的类属性仍然会受到影响

对象属性

对象属性是依据类创建对象的时候,每个对象都具有的公共属性

其数值的更改需要通过调用对象属性赋值来修改,不能通过类属性更改

总结

类属性,不允许对象私自修改,有类统一修改,影响所有对象

对象属性,依据对象的特点,可以自己做出特定的修改。类没有权限去修改对象属性

对象方法
  • 理解
class student(object):
    tall = 'tom'                           # 类属性,其变化同于基础部分的讲解
    def __init__(self, nickname):                     # 魔术方法
        self.name = nickname                 # 对象属性,应用到具体对象都会给定一个初始值,可根据具体需要再做修改
        self.age = 'None'
        self.phone = 'None'

    def run(self):
        print("{}在跑步".format(self.name))	# 调用对象属性
        print("{}在跑步".format(self.tall))	# 调用类属性
        self.sleep()					 # 调用其他对象方法

    def sleep(self):
        print('在睡觉')


# basic
lily = student('dahuang')
lily.sleep()
lily.run()

在睡觉
dahuang在跑步
tom在跑步
在睡觉

对象方法

可以调用类属性,也可以调用对象属性

对象方法中的参数是对象self

对象方法之间可以相互调用

类方法
  • 理解
class student(object):
    tall = 'tom'                           # 类属性,其变化同于基础部分的讲解
    def __init__(self, nickname):                     # 魔术方法
        self.name = nickname                 # 对象属性,应用到具体对象都会给定一个初始值,可根据具体需要再做修改
        self.age = 'None'
        self.phone = 'None'

    def sleep(self):
        print('在睡觉')

    @classmethod
    def test(cls):
        print('只能调用类属性:',cls.tall)

# basic
student.test()

只能调用类属性: tom

类方法

依赖装饰器,且只能调用类属性,不能调用对象属性(会报错)

类方法中的参数是类,不依赖对象,可以独立于对象做一些处理

类方法中不能调用对象方法

  • 类方法和对象方法的理解

类属性是公共属性,对象属性是私有属性

类方法只能调用类属性;而对象方法既能调用对象属性,也能调用类属性

静态方法
class student(object):
    __tall = 'tom'                              # 对类属性进行私有化
    high = 12
    def __init__(self, nickname):
        self.name = nickname
        self.age = 'None'
        self.phone = 'None'

    def sleep(self):
        print('在睡觉')

    @staticmethod
    def casual():
        print('只能调用类属性tall:', student.__tall)
        print('只能调用类属性high:', student.high)


# basic
student.casual()

只能调用类属性tall: tom
只能调用类属性high: 12

也是只能访问公共类属性

静态方法和类方法区别

不同

  • 装饰器不同
  • 参数不同,一个有cls,一个无cls

相同

  • 都只能访问类属性和方法,对象属性和对象方法无法访问
  • 都可以通过类名调用访问
  • 都可以在对象创建之前调用,不依赖于对象
总结–↑
  • 几种方法都可以接受外部参数
class student(object):
    __tall = 'tom'                              # 对类属性进行私有化
    high = 12
    def __init__(self, nickname):
        self.name = nickname
        self.age = 'None'
        self.phone = 'None'

    def sleep(self, outer1):
        print('outer1:', outer1, self.__tall, self.high)

    @classmethod
    def casual(cls, outer2):
        print('outer2:', outer2, cls.__tall, cls.high)

    @staticmethod
    def casual(outer3):
        print('outer3:', outer3, student.__tall, student.high)

# basic
student('dahuang').sleep(1)
student.casual(2)
student.casual(3)

outer1: 1 tom 12
outer3: 2 tom 12
outer3: 3 tom 12

  • 各自特点

对象方法

  • 可以调用对象属性,也可以调用类属性(私有和非私有的)
  • 依赖对象,没有对象就不能调用对象方法
  • 没有装饰器
  • 必须有self对象参数,也可以有外部参数

类方法

  • 只能调用类属性(私有的和非私有的)
  • 不依赖对象,没有对象也可以调用类方法
  • 需要装饰器,classmethod
  • 必须有cls参数,也可以有其他外部参数

静态方法

  • 只能调用类属性(私有和非私有的)
  • 不依赖对象,没有对象也可以调用静态方法
  • 需要装饰器,staticmethod
  • 不需要任何参数,但是也可以添加外部参数

面向对象–魔术方法

魔术方法
  • http://c.biancheng.net/view/7817.html
  • https://www.cnblogs.com/zhangboblogs/p/7860929.html
  • https://www.cnblogs.com/nmb-musen/p/10861536.html
常用魔术方法
# __new__(self)  和  __init__(self)
# 先执行new,再执行init,不要随便动用new魔术方法

class Test:
    def __init__(self):
        print("init方法")

    def __new__(cls, *args, **kwargs):
        print("重写new方法")
        return super().__new__(cls)


m = Test()

重写new方法
init方法

# _del__(self) :析构器
# 当一个实例被销毁的时候调用的方法
# 非手动调用时会在程序最后触发,而手动调用del时则会触发__del__,并不是程序最后

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

    def __del__(self):
        print("触发__del__")


t = Test("python")
print("end")

del t
print("end")
# __len__

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

    def __len__(self):
        return len(self.name) # 必须有返回值,且必须为int类型


t = Test("mingming")
print(len(t))

8

# __str__

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

    def __str__(self):
        return "hello world" #必须有返回值,且必须为str类型

# 调用方法1
t = Test("mingming")
print(t)

# 调用方法2
print(t.__str__())

hello world

hello world

# __bool__

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

    def __bool__(self):
        if self.name =="python": # 返回对象必须是True 或 False
            return True
        else:
            return False

t = Test("python")
t1 = Test("java")
print(bool(t))
print(bool(t1))

True

False

面向对象–私有化

类属性的私有化
  • 目的

为了防止外部任意修改公共类属性

私有化的类属性只能够被类方法修改

class student(object):
    __tall = 'tom'                              # 对类属性进行私有化
    high = 12
    def __init__(self, nickname):
        self.name = nickname
        self.age = 'None'
        self.phone = 'None'

    def sleep(self):
        print('在睡觉')

    @classmethod
    def test(cls):
        print('只能调用类属性tall:',cls.__tall)
        print('只能调用类属性high:', cls.high)

    @classmethod
    def update(cls):
        cls.__tall = '把tom改为tttom'
# basic
student.test()
student.high = '修改后'
student.tall = '修改后'    # 私有属性,不可外界修改
student.test()

student.update()         # 使用类方法修改私有属性
student.test()

只能调用类属性tall: tom
只能调用类属性high: 12
只能调用类属性tall: tom
只能调用类属性high: 修改后
只能调用类属性tall: 把tom改为tttom
只能调用类属性high: 修改后

对象属性的私有化
  • 目的

为了防止对象属性被不合理的修改

可以通过对象方法来修改私有的对象属性

class PositiveInteger():
    def __init__(self):
        self.__name = 'Tom'
        self.__age = 15

    def setName(self, newname):
        self.__name = newname

    def setAge(self, newage):
        if 0 < newage < 100:
            self.__age = newage
        else:
            print('年龄不符合要求')

    def __str__(self):
        return '学生的年龄:{},学生的名字:{}'.format(self.__age, self.__name)

i = PositiveInteger()

print(i)
# i.__name    这是无法修改的
i.setName('TTTTom')
i.setAge(150)
print(i)

学生的年龄:15,学生的名字:Tom
年龄不符合要求
学生的年龄:15,学生的名字:TTTTom

私有化的本质–↑
  • 本质是通过修改内部的名字,让你无法通过原名字访问
  • 可以找到真实的名字进行访问,但是不建议这样用
class PositiveInteger():
    __name1 = 'lily'

    def __init__(self):
        self.__name = 'Tom'
        self.__age = 15

    def setName(self, newname):
        self.__name = newname

    def setAge(self, newage):
        if 0 < newage < 100:
            self.__age = newage
        else:
            print('年龄不符合要求')

    def __str__(self):
        return '学生的年龄:{},学生的名字:{}'.format(self.__age, self.__name)


i = PositiveInteger()

print(dir(PositiveInteger))
print(dir(i))		# 等价于 i.__dir__()

print(i)
i._PositiveInteger__age = 99	# 不过不建议这样修改
print(i)

学生的年龄:15,学生的名字:Tom
学生的年龄:99,学生的名字:Tom

@property
  • 目的

即想达到对象属性私有化的目的

又想通过 对象.属性 的方法来调用和修改私有化后的属性

class PositiveInteger():

    def __init__(self):
        self.name = 'Tom'
        self.__age = 15

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

    @age.setter
    def age(self, newage):
        if 0 < newage < 100:
            self.__age = newage
        else:
            print('年龄不符合要求')

    def __str__(self):
        return '学生的年龄:{},学生的名字:{}'.format(self.__age, self.name)


i = PositiveInteger()

print(i, i.age)
i.age = 99
print(i, i.age)

学生的年龄:15,学生的名字:Tom 15
学生的年龄:99,学生的名字:Tom 99

面向对象–关联关系

概念辨析
  • is a

是一种继承关系

A is a B B是A的基类(父类)

可以产生代码上的重用性

比如:兔子 is a 动物

就是说兔子继承了动物的一些特点:有腿、有耳朵

具体到代码层面就是说:它可以继承动物(父)类的一些属性,如果有需要增加的可以再写

兔子爱吃的素食有哪些,就是兔子类不能从动物类继承的属性,因为有些动物不吃素的

就可以在动物类的基础上,添加喜欢吃的食物这一属性

  • has a

是一种包含关系

A has a B A包含B

比如:汽车 has a 轮胎,但是不能说汽车 is a 轮胎

包含关系具体到代码层面就是调用

汽车有很多属性:轮胎类型、车座类型、价格…

轮胎也有很多属性:价格、材质、防滑等级…

汽车对象就可以调用轮胎对象里面的一些属性

宝马牌汽车的轮胎是米其林材质的,价格是…。防滑等级是…

实例理解

讲的是 has a的包含关系

is a的继承关系在后续有介绍

class Compter:
    def __init__(self,brand,type,color):
        self.brand=brand
        self.type=type
        self.color=color

    def online(self):
        print("正在使用电脑上网")

    def __str__(self):
        return self.brand + '-------'+self.type+'------'+self.color

class Book:
    def __init__(self,bname,number,author):
        self.bname=bname
        self.number=number
        self.author=author

    def __str__(self):
        return self.bname+self.author+self.number

class sudent:
    def __init__(self,name,compter,book):
        self.name=name
        self.compter=compter
        self.Book=[]
        self.Book.append(book)
    def __str__(self):
        return self.name+'------->'+str(self.compter)+'-----'+str(self.Book)

C=Compter('mac','pro','深灰色')
print(C)
print(type(C))

s = sudent('lilu', C, '盗墓笔记')
print(s)

mac-------pro------深灰色
main.Compter’>
lilu------->mac-------pro------深灰色-----[‘盗墓笔记’]

面向对象–继承关系

基本继承
class person():
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print('{}岁的{}在跑步'.format(self.age, self.name))


class sudent(person):
    def __init__(self, name, age, classes):
        super().__init__(name, age )
        self.classes = classes

    def run(self, food):
        super().run()
        print('他是{}的,喜欢吃{}'.format(self.classes, food))


s = person('lilu', 13)
s.run()

s = sudent('lilu', 14, '15班')
s.run('汉堡')

13岁的lilu在跑步
14岁的lilu在跑步
他是15班的,喜欢吃汉堡

  • init问题
子类不定义init,则从父类继承

子类继承父类,但是也需要自己定义
def __init__(self, name, age, classes):
    super().__init__(name, age)
    self.classes = classes
  • 对象方法
父类定义eat()对象方法,子类无定义
	参数结果均同于父类
    默认搜索原则:先搜索当前类,没有的话,再搜索父类

父类定义eat()方法,子类也定义
	父类提供的方法无法满足子类需求,在子类中定义一个同名的方法,就叫做:重写
    子类定义的同名方法,可以借助父类中定义的部分
    def run(self, food):
        super().run()
        print('他是{}的,喜欢吃{}'.format(self.classes, food))
  • 注意

父类中私有的属性,子类是无法继承的

多重继承
  • https://www.cnblogs.com/xpc51/p/11764975.html
class Base():
    def run(self):
        print('Base')


class A(Base):
    def run(self):
        print('Base')


class B(Base):
    def run(self):
        print('Base')


class C(Base):
    def run(self):
        print('Base')


class D(A, B, C):
    def run(self):
        print('Base')

print(D.__mro__)

-----------------------------------------
(<class 'main.D'>, <class 'main.A'>, <class 'main.B'>, <class 'main.C'>, <class 'main.Base'>, <class 'object'>)

多重继承的顺序问题在Python2有这个问题

在Python3中没有这个问题

面向对象–多态

多态介绍
#   封装  继承  多态 ----》 面向对象
class Person:
    def __init__(self, name):
        self.name = name

    def feed_pet(self, pet):  # pet既可以接收cat,也可以接收dog,还可以接收tiger
        # isinstance(obj,类)  ---》 判断obj是不是类的对象或者判断obj是不是该类子类的对象
        if isinstance(pet, Pet):
            print('{}喜欢养宠物:{},昵称是:{}'.format(self.name, pet.role, pet.nickname))
        else:
            print('不是宠物类型的。。。。')


class Pet:
    role = 'Pet'

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

    def show(self):
        print('昵称:{},年龄:{}'.format(self.nickname, self.age))


class Cat(Pet):
    role = '猫'

    def catch_mouse(self):
        print('抓老鼠....')


class Dog(Pet):
    role = '狗'

    def watch_house(self):
        print('看家高手....')


class Tiger:
    def eat(self):
        print('太可怕了,可以吃人...')


# 创建对象
cat = Cat('花花', 2)

dog = Dog('大黄', 4)

tiger = Tiger()

person = Person('家伟')

person.feed_pet(cat)
person.feed_pet(dog)
print('----------------------------')
person = Person('pengpeng')

person.feed_pet(tiger)

# Pet
#  pet  父类      cat   dog 子类
#  pet  大类型    cat  dog 小类型
  • python中没有严格的多态,它的多态实现是通过 isinstance() 函数来实现的

即不能分辨接受对象所属的类型,所有类型的对象都可以接受

但是可以通过isinstance()函数,来分辨对象的类型,从而做出不同的动作

总结–多态、继承、封装
  • 基本概念

封装

根据功能将属性和方法封装在一个个类中,然偶基于这些类来创建对象

有些属性不希望外界随便更改,就给私有化

留有接受和改变该属性的方法

但是改变有条件,通过写在改变该属性的方法里面

继承

降低代码的冗余度,实现了代码的复用

多态

不同对象调用同一个方法,可能产生不同的结果

python中没有严格的多态,主要是通过isinstance()函数来实现对象类型的判断分别

  • 参考文献

https://www.jianshu.com/p/f78cab5deb9a

https://blog.csdn.net/simuLeo/article/details/80067619

https://www.liujiangblog.com/course/python/44

https://blog.csdn.net/weixin_48261286/article/details/113747011

你可能感兴趣的:(Python知识点,python)