注重对象和指责,不一样的对象承担各自的指责算法
更加适合对复杂的需求变化,专门应对复杂项目开发,提供固定的套路编程
面向对象强调的是谁来作,面向过程强调的如何作app
类是对一群具备相同特征或者行为的事物统称,是抽象的,不能直接使用,特征被称为属性,行为被称为方法,类就是一个模板ide
对象是由类建立出来的一个具体存在,能够直接使用,经过哪一个类建立出来的实例,就拥有哪一个类中定义的特征和行为函数
类是模板,对象是根据类这个模板建立出来的,先有类,再有对象code
类只有一个,对象有多个对象
类中定义的方法属性都会存在对象中,很少很多继承
不一样的对象之间的属性不尽相同内存
方法名 | 类型 | 做用 |
---|---|---|
new | 方法 | 经过类()建立对象时,向内存申请空间,并将对象引用传递给init |
init | 方法 | 对象初始化时,会调用此方法 |
del | 方法 | 对象被销毁时,会调用此方法 |
str | 方法 | 返回对象的描述信息 |
class Cat: """这是一个猫类""" def eat(self): print("小猫爱吃鱼") def drink(self): print("小猫在喝水") tom = Cat() tom.drink() tom.eat()
对象中的self参数开发
在类封装的方法内部,self就表示当前调用方法的对象本身 调用方法时,不须要传递self参数 在方法内部能够经过self.访问对象的属性 也能够经过self.调用其余的对象方法 class Cat: def __init(self,name) self.name = name def eat(self): print("%s 爱吃鱼" % self.name) tom = Cat('mimimi') tom.eat()
封装是面向对象编程的一大特色
面向对象将属性和方法封装到一个抽象的类中
外部使用类建立对象,而后让对象调用方法
对象方法的细节都被定义到类的内部
DFS(深度优先算法):
class E: def say(self): print('E') class D: pass class C(E): pass class B(D): pass class A(B,C): pass a = A() a.say() # 查找顺序 A->B->D->C->E
BFS(广度优先算法):
class E: def say(self): print('E') class D: pass class C(E): pass class B(D): pass class A(B,C): pass a = A() a.say() # 查找顺序 A->B->C->D->E
C3(算法):
class F: def say(self): print('F') class E(F): pass class D(F): pass class C(E): pass class B(D): pass class A(B,C): pass a = A() a.say() print(A.__mro__) # (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class 'object'>) # 查找顺序 A->B-?>D-C->E-F
Python中不支持多态,也不用支持多态,Python是一种多态语言,崇尚鸭子类型,鸭子类型的概念来自于:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就能够被称为鸭子,Python不会检查类型是否是鸭子,只要它拥有鸭子的特征,就能够被正确的调用
class Duck: def speak(self): print('嘎嘎嘎...') class Dog: def speak(self): print('汪汪汪...') class Cat: def speak(self): print('喵喵喵...') animal = [] animal.append(Duck) animal.append(Dog) animal.append(Cat) for i in animal: i().speak() # 嘎嘎嘎... # 汪汪汪... # 喵喵喵...
实例方法第一个参数必须是self,经过实例方法来传递实例的属性和方法,只能同实例来调用,静态方法使@staticmethod装饰器来定义,参数随意,静态方法是一个独立的函数,它仅仅依托于类的命名空间,不会涉及到类是属性和方法的做,静态方法由于没有参数绑定到该类因此仅仅提供函数功能,不能调用实例属性或静态属性,类方法使用@classsmethod来定义,第一个参数必须是cls,经过它传递类的属性和方法,类方法只能调用静态属性
class Data(): def __init__(self,year,month,day): self.year = year self.month = month self.day = day @staticmethod def static_method(date_str): year,month,day = tuple(date_str.split('-')) return Data(int(year),int(month),int(day)) @classmethod def class_method(cls,date_str): year, month, day = tuple(date_str.split('-')) return cls(int(year), int(month), int(day)) def object_method(self): print(self.year,self.month,self.day,sep='-') if __name__ == '__main__': date = Data(2018,9,15) date.object_method() # 2018-9-15 date = Data.class_method('2018-9-16') date.object_method() # 2018-9-16 date = Data.static_method("2018-9-17") date.object_method() # 2018-9-17
类变量,能够经过类调用,也能够经过实例调用,在内存中之存在一份
实例变量,只能经过实例调用,每一个对象都有一份
class Person: country = "中国" def __init__(self,name,age): self.name = name self.age = age p1 = Person('kernel',18) print(p1.name) # kernel print(p1.age) # 18 print(p1.country) # 中国 print(Person.country) # 中国 p1.country = "美国" # 当经过对象修改类变量时,将会在该对象建立一个和类变量同名的变量,类变量依然不变 print(p1.country) # 美国 print(Person.country) # 中国 p2 = Person('alex',38) print(p2.name) # alex print(p2.age) # 38 print(p2.country) # 中国
class User: def __init__(self,name,age): self.name = name self.__age = age def get_age(self): print(self.__age) def set_age(self,age): self.__age = age if __name__ == '__main__': u = User('kernel',18) # print(u.__age) # AttributeError: 'User' object has no attribute '__age' 好吧,私有属性不让我访问,可是真的没法访问吗 print(u._User__age) # 但这又是什么鬼呢?固然咱们不建议这么干 u.set_age(19) u._User__age=20 # 固然,设置也能够这样 u.get_age() # 20
使用类名()建立对象,首先会调用new方法为对象分配空间,它的主要做用就是在内存中为对象分配空间和返回对象的引用,Python解释器获得对象的引用后,将引用传递给init
定义一个类属性,初始值是None,用于记录单例对象的引用
重写new方法
若是类属性是None,调用方法申请空间,并在类属性中记录
返回类属性中纪录的对象引用
class MusicPlayer(object): instance = None # 记录第一个被建立对象的引用 init_flag = False # 记录是否执行过初始化动做 def __new__(cls, *args, **kwargs): if cls.instance is None:# 判断类属性是不是空对象 cls.instance = super().__new__(cls) # 调用父类的方法,为第一个对象分配空间 return cls.instance # 返回类属性保存的对象引用 def __init__(self): if not MusicPlayer.init_flag: MusicPlayer.init_flag = True player1 = MusicPlayer() # <__main__.MusicPlayer object at 0x0000017C297F99E8> print(player1) player2 = MusicPlayer() # <__main__.MusicPlayer object at 0x0000017C297F99E8> print(player2)