一、面向对象书写
class Car: # self表示当前类对象,当前你创建的是谁,谁来访问这个方法,self就是谁 def __init__(self, color, displacement, number): self.color = color self.displacement = displacement self.number = number def run(self, speed): print(f"这辆车可以跑{speed}迈") #实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征 car = Car("red", "1.8T", "京A88888") car.run(100)
1. __new__(cls, *args, **kwargs) __new__ 负责对象的创建而 __init__ 负责对象的初始化;至少需要传递一个参数cls,必须要有返回值,返回实例化出来的实例。可以return父类通过super(当前类名,cls).__new__出来的实例,或者直接是object的__new__出来的实例。 2. __init__() - 构造方法 __init__()在__new()的基础上完成初始化动作,不需要返回值;有一个参数self,该self参数就是__new__()返回的实例; 3. 实例 class B(): def __new__(cls, *args, **kwargs): print("__new__方法被执行") return super(B, cls).__new__(cls) def __init__(self): print("__init__方法被执行") b = B()
二、继承
1、新式类与经典类
- 新式类:继承了object类以及该类的子类都是新式类;Python3中如果没有继承任何类,则默认继承object类。因此Python3中都是新式类(广度优先遍历)
- 经典类:没有继承object类以及该类的子类,都是经典类;在Python2中如果一个类没有继承任何类,不会继承object类(深度优先遍历)
2、抽象与派生
(1) 抽象:通过抽象可以得到类,抽象是一种分析的过程。比如,猪八戒、小猪佩奇可以抽象出一个类,就是猪类;接着还可以从猪类、狗类抽象出动物类。先分析、抽象之后,就可以通过继承,在程序上实现这个结构。
(2) 派生:就是在子类继承父类的属性的基础上,派生出自己的属性。子类有不同于父类的属性,这个子类叫做派生类。
class Animals: def __init__(self, name): self.name = name def walk(self): print('我会走') class Dog(Animals): # Dog类派生出bite功能 # 派生:狗有咬人的技能 def bite(self): print('我会咬人')
3、组合
class Mobile(): def __init__(self, color): self.color = color def call(self): print("打电话") class People(): def __init__(self, name, mobile): self.name = name self.mobile = mobile mobile = Mobile("red") people = People("Tom", mobile) people.mobile.call()
4、属性查找顺序
对象自己->所在类中->找父类->父类的父类->Object
5、多继承
class ParentOne: pass class ParentTwo: pass class SubClass(ParentOne, ParentTwo): pass #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类 print(SubClass.__bases__) >(<class '__main__.ParentOne'>, <class '__main__.ParentTwo'>)
MRO顺序 >F.MRO() >[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
三、覆盖(overrides)
1、子类访问父类内容
注:当子类出现了和父类名称完全一致的属性或方法 方式一 super.(当前类名称, self).你要调用的父类的属性或方法 方式二 super().你要调用的父类的属性或方法 方式三 类名称.你要调用的父类的属性或方法(self)
注:当你继承一个现有的类,并且你覆盖了父类的init方法时,必须在初始化方法的第一行调用父类的初始化方法,并传入父类所需的参数 练习:实现一个可以现在元素类型的容器(字典、列表、元组、集合、字符串) class MyList(list): def __init__(self, element_type): # 调用父类初始化方法来完成基本的初始化 super().__init__() self.element_type = element_type def append(self, object): """ :param object: 是要存储的元素 :return: 无 """ if type(object) == self.element_type: super(MyList, self).append(object) else: print(f"sorry, you element type not is {self.element_type}") m = MyList(int) m.append(1) print(m[0]) m.append("11")
四、封装
1、类成员-属性
1. 实例变量(字段) 2. 类变量(静态变量) 每个实例都应该拥有的变量. 比如.在上述事例中电影的的名字,电影的类型, 电影的语言,电影的时长,都是实例变量而类变量就是这一类事物统一拥有的变量,比如上述事例中可以说这些个电影都可以是3D(规定下),类变量最好是用类名来访问 方式一: class Movie: film_format="3D" def __init__(self,genre,language,name,time): self.genre=genre self.language=language self.name=name self.time=time def show(self): print("%s在中国上映" %self.name) M1 = Movie("剧情","国语","少林足球","2H") M2 = Movie("喜剧","国语","大话西游","2H") Movie.film_format="2D" #把类变量中的值改了,都跟着变了. print(M1.film_format) #2D print(M2.film_format) #2D 方式二: class Movie: film_format="3D" def __init__(self,genre,language,name,time): self.genre=genre self.language=language self.name=name self.time=time def show(self): print("%s在中国上映" %self.name) M1 = Movie("剧情","国语","少林足球","2H") M2 = Movie("喜剧","国语","大话西游","2H") M1.film_format="2D" print(M1.film_format) #2D print(M2.film_format) #3D
2、类成员-方法
(1)成员方法 - 对象直接可以访问的方法
class Computer: # 成员方法 def play(self): print("play game!") computer = Computer() computer.play()
(2)静态方法
不需要给方法传递self;即当出现一个方法不需要用到成员变量时[@staticmethod]
class Person: def __init__(self): pass # 实例方法需要传递类的对象self def think(self): print("人能思考") @staticmethod def calculate(a, b): return a + b # 类名可以访问 person = Person.calculate(1, 2) print(person) > 3
(3)类方法
当方法需要传递类名时,需要类方法[@classmethod]
class Person: def __init__(self): pass # cls表示类 @classmethod def clsMethod(cls): # 可以动态创建对象 person = cls() print("我是一个类方法", person) # 类方法默认第一个参数接受的是类名 Person.clsMethod() > 我是一个类方法 <__main__.Person object at 0x00000241E7A17358>
3、类成员-属性
应用场景: 我们⼀般保存数据的时候, 不会保存⼀个⼈的年龄. 因为随着时间的推移. 每个人的年年龄都时刻在改变着. 那如何保存更更加完美呢? 很简单. 保存出生年年月日. 然后用程序来 计算,你当前的年龄实时的那这个时候就需要进行行相应的计算了了. 而计算属于⼀个功能. 当然要写方法里了. 但是对于年年龄这个属性而言. 他应该是一个数值. 而不是动作. 所以python 就提供了这样⼀种机制. 通过方法来描述⼀个属性.
注意:
- 方法参数只能有⼀个self
- 方法上方要写@property
- 调用的时候, 我们不需要写括号. 直接当成属性变量量来用就可
- 这种套路只能取值. 不能设置值
class Person: def __init__(self, name, num, gender, birthday): self.name = name self.num = num self.gender = gender self.birthday = birthday # 表示当前方法是一个属性.方法的返回值就是这个属性的值 @property def age(self): # 方法只能有一个参数self;可以是计算结果,必须有返回值 return 10 * 9 person = Person("alex", "10086", "不详", "1989-01-02") print(person.age) > 90
4、私有
(1)私有变量
私有的内容不能直接访问,但是如果对方开辟了外界访问的通道(公共方法),那可以通过这个公共的方法来获取到私有的内容,这样做的好处是. 外界只能看, 但是改不了.
class Tiger: def __init__(self, name,figure, money): self.name = name self.figure = figure self.__money = money def buy(self): print(f"我有{self.__money}这么多钱") tiger = Tiger("永康", "正直", "1亿") tiger.buy() > 我有1亿这么多钱
(2)私有方法
class Tiger: def __init__(self,name,figure,style,qingfu,money,fangchan): self.name = name self.figure = figure self.style = style self.__qingfu = qingfu self.__money = money self.__fangchan=fangchan def buy(self): print("我有%s这么多钱" % self.__money) #我有10亿这么多钱 self.__sel() def __sel(self): print("我要卖掉%s套房" % self.__fangchan) T1=Tiger("呵呵","正直","廉洁","潘潘","10亿","10") T1.buy() >我有10亿这么多钱 >我要卖掉10套房
五、单例模式
import threading # 多线程情况下需要加锁,因为它们共享一个内存 class Singleton(object): _instance = None _lock = threading.RLock() # cls是当前正在实例化的类;初始化一块内存 def __new__(cls, *args, **kwargs): # 如果已创建实例,直接返回即可 if cls._instance: return cls._instance # 加锁 with cls._lock: if not cls._instance: cls._instance = super().__new__(cls, *args, **kwargs) return cls._instance
来源:https://www.cnblogs.com/hq82/p/12587764.html