类属性与对象属性
类中应该仅存储所有对象共有的内容
如所有人的国籍相同那就放到类中
对象中存储每个对象独有的内容
如每个人的名字都不同
初始化函数
class Person:
color = 'white'
def read(self):
print('hamlet')
# 创建对象 也称之为实例化 产生的对象也称之为实例
a1=Person()
print(a1)
print(a1.color)
print(a1.__dict__)
a2 = Person()
print(a2)
print(a2.read())
print(a2.__dict__)
print(id(a1.color))
print(id(a2.color))
print(id(Person.color))
# 当修改某一个对象的属性时 ,不会影响其他对象和类
a2.color = 'black'
print(a2.color)
print(a1.color)
print(Person.color)
例子
class Person:
people = 'mingren'
def student(self):
print('正在练习')
peo1 = Person()
# print(peo1)
peo1.name='索隆'
peo1.height=185
peo2 =Person()
peo2.name = '路飞'
peo2.height =180
# 封装一个方法来初始化对象的属性
def my__init(peo,name,height):
peo.name=name
peo.height=height
peo1=Person()
peo2=Person()
my__init(peo1,'索隆',185)
my__init(peo2,'路飞',180)
print(peo1.name)
print(peo1.height)
print(peo2.name)
print(peo2.height)
# __init__方法的使用
# init 是初始化的缩写 用于为对象的属性设置初始值
# 特点
# 执行时机:当实例化产生对象时会自动执行该函数
# 会自动传入需要初始化的对象
# 初始化必须包含至少一个参数 用于表示对象本身
# 该函数不允许有返回值 必须为None
class Cat:
def __init__(self,age,name,**kwargs):
# print(self)
self.age=age
self.name=name
a1=Cat(1,'花花')
a2=Cat(2,'草草')
print(a1.name)
print(a2.name)
绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入):
1. 绑定到类的方法:用classmethod装饰器装饰的方法。
为类量身定制
类.boud_method(),自动将类当作第一个参数传入
(其实对象也可调用,但仍将类当作第一个参数传入)
2. 绑定到对象的方法:没有被任何装饰器装饰的方法。
为对象量身定制
对象.boud_method(),自动将对象当作第一个参数传入
(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)
绑定方法
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
# 默认情况下 在类中定义的方法 都是绑定方法
def say_hio(self):
print('i am %s'% self.name)
# 当你创建对象时 发生什么
# 1.产生一个空对象 (名称空间)
# 2.自动调用__init__方法 并且把这个对象以及额外的参数传入
a1=Person('山治',19)
a1.say_hio()
a2=Person('娜美',18)
a2.say_hio()
# 经常使用的数据定义为变量
username='josn'
pwd='1234'
db_name='wechat'
atm_user='rosc'
atm_pwd='14778'
#用于登录数据库
def login_data_base(username,pwd,db_name):
print('%s登录%s数据库 密码为%s'%(username,db_name,pwd))
def login_atm(username,pwd):
print('%s登录了ATM 密码为%s'%(username,pwd))
login_data_base(username,pwd,db_name)
login_atm(atm_user,atm_pwd)
# login_data_base("rose","321","weix")
#绑定的好处是
#将数据以及处理数据的方法绑定在一起
#拿到对象就同时拿到数据和处理的方法
#直接调用即可
# 可以这么理解 :
# 面向对象其实就是提高整合程度
# 把数据和方法整合到一起
绑定方法与普通函数的区别
当使用类调用时,就是一个普通函数 有几个参数就得传几个参数
当用对象来调用时,是一个绑定方法了,会自动将对象作为第一个参数传入
绑定方法与非绑定方法
一个类中可以有属性和方法
方法分为两种
1.绑定方法
1对象绑定方法
在使用对象调用时会自动传入对象本身
2类绑定方法
classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数(即便是对象来调用也会将类当作第一个参数传入),python为我们内置了函数classmethod来把类中的函数定义成类方法
@classmethod
在使用对象调用时会自动传入类本身
在使用类来调用时也会自动传入类本身
单例模式中就会经常使用@classmethod
类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样
到底绑定给谁?
当你的方法执行过程中需要使用到对象中数据时就绑定给对象
当你的方法执行过程中需要使用到类中数据时就绑定给类
2.非绑定方法
非绑定方法:用staticmethod装饰器装饰的方法
1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已
注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说
即不需要对象中的数据 也不需要类中的数据 那就定义为非绑定方法,就是普通函数
在类内部用staticmethod装饰的函数即非绑定方法,就是普通函数
statimethod不与类或对象绑定,谁都可以调用,没有自动传值效果
@staticmethod
class Student:
school='hanghai'
def __init__(self,name):
self.name=name
# 默认情况下是绑定方法
def study(self):
print(self)
# 对于类而言study就是普通函数
# 而对于对象而言 他是一个绑定方法 当使用对象来调用时 会自动将对象作为第一个参数传入
import time
class Person:
country = 'china'
def __init__(self,name,age):
self.name=name
self.age=age
@classmethod
def info(cls):
print(cls)
print('info go')
def say_no(self):
print('no good %s'%self.name)
# q=Person('rose',20)
# q.info()
# print(Person)
# print(Person.info)
# Person.info()
# p = Person("rose",10)
# p.say_no()
# 是要输出这个类的一些信息
@classmethod
def class_info(cls):
print('the class %s is module xxx.py'%cls.__info__)
# 输出当前时间
# 不需要访问类也不需要访问对象 所以直接做成非绑定方法
@staticmethod
def show_time(self):
print(time.localtime())
q=Person('rosc',1)
q.show_time(1)
继承:
继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。
子类会“”遗传”父类的属性,从而解决代码重用问题
在OOP中 继承描述是类和类之间的关系 例如b类继承a类 b类可以直接使用a类中的属性和方法
a是父类(基类,超类) b是子类(派生类)
好处:极大的提高了代码的复用性
如何使用继承,至少需要两个类
语法:
class 子类名称(父类名称):
pass
抽象与继承
继承之后可以直接使用父类的属性和方法
使用继承时 应该先抽象 在继承
抽象指的是 将一系列类中相同的特征和相同行为抽取 形成一个新的类
会产生一些与原本业务不相关的类
站在不同角度会得到不同的抽象结果
![抽象过程](C:\Users\dell\Desktop\抽象过程.png)
继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
例子
class OLDBIOYPerson:
school='oldboy'
def __init__(self,name,age):
self.name=name
self.age=age
def say_no(self):
print('hello %s'%self.name)
class Teacher(OLDBIOYPerson):
def teach(self):
print('正在备案...')
class Student(OLDBIOYPerson):
pass
# 测试
a=Teacher('ice',26)
a.say_no()
a.teach()
w=Student('paper',24)
w.say_no()
--不重要
__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
class ParentClass1:
pass
class ParentClass2:
pass
class SubClass1(ParentClass1):
pass
class SubClass2(ParentClass1,ParentClass2):
pass
# __base__只查看从左到右继承的第一个子类,
# __bases__则是查看所有继承的父类
print(SubClass1.__bases__)
print(SubClass2.__bases__)
print(SubClass2.__base__)
# 一切皆对象指的是
# 在python3中任何类都直接或间接继承自Object
# Object是所有类的基类 (根类)
# 其中提供一系列方法, 这样一来 无论你是什么类 ,你都可以直接是object中已经存在的方法
# 一切皆对象
在python中您所使用到的任何数据都是对象 int float list dict 模块 包
class Test:
pass
a = 10
print(type(a))
li = []
print(type(li))
t = Test()
print(type(t))
查找顺序
class A:
name='ham'
# def __str__(self):
# print('111111')
# pass
pass
class B(A):
name ='rose'
pass
b=B()
b.name='aaa'
print(b.__str__())
# 查找顺序
# 对象自己 - > 所在的类 -> 所在类的父类 -> 父类的父类 -> object
派生与覆盖
'''派生
当一个类继承自另一个类 并且这个子类拥有与父类不同的内容 就称之为派生
'''
class A:
def info(self):
print('hello world')
class B:
pass
'''
覆盖 (重写)
子类中出现了与父类名称相同的属性 或方法 就会覆盖掉父类的属性或方法
'''
class A:
text='124'
def info(self):
print('hello')
class B(A):
text='529'
def info(self):
print('hello,asedrk')
pass
b=B()
b.info()
print(b.text)
访问父类的内容
class Person:
text='147'
def __init__(self,name,age,):
self.name=name
self.age=age
def sleep(self):
print('吃饭,睡觉,打豆豆')
def say_no(self):
print('name:%s,age:%s'%(self.name,self.age),end='')
class Student(Person):
text='852'
# 由于父类已经存在一个方法可以完成这个三参数的初始化
# 所以可以直接调用父类的初始化完成这部分的初始化工作
def __init__(self,name ,age,number):
# [1]指名道姓的调用
Person.__init__(self,name,age)
# [2]super()
super().__init__(name,age)
# py2的写法
# super(Student, self).__init__(name,age,gender)
self.number=number
# 访问父类的属性
def show_text(self):
print(self.text)
print(super().text)
def say_hi(self):
super().say_hi()
print("my number: %s" % self.number)
s = Student("jack",20,"man",)
s.say_no()