class JackPerson: # 首字母大写,命名驼峰原则
# 实例变量
def __init__(self, k): # 初始化方法,自动执行方法
self.data = k
# 绑定方法
def xxx(self, x, y): # 定义一个方法
data = x + y
print(data, self.data)
def yyy(self, i, j):
data = i * j
print(data, self.data)
# 1、根据类创建一个对象,内存的一块区域
# 2、执行__init__方法,模块会将创建的那块区域地址当self参数传进去
# 3、内部方法可以相互调用
a = JackPerson('你好') # 实例化一个对象i,创建一块区域,初始化一些数据
a.xxx(1, 2) # 3 你好 也可以用JackPerson.xxx(a,1,2)
a.yyy(2, 3) # 6 你好
b = JackPerson('哈哈')
b.xxx('人','狗') # 人狗 哈哈
b.yyy('猫',2) # 猫猫 哈哈
class UserInfor:
def __init__(self,name,psw):
self.name = name
self.psw = psw
def run():
userinfor = []
while True:
user = input('请输入用户名:')
if user.upper() == 'Q':
break
psw = input('请输入密码:')
user_objct = UserInfor(user,psw)
userinfor.append(user_objct) # 将每次输入的用户名和密码实例化,并将这一实例化对象放进列表里,列表里是一块块的内存
print(userinfor) # 类似于[<__main__.UserInfor object at 0x000001C40A645D60>, <__main__.UserInfor object at 0x000001C40A645D00>]
for i in userinfor:
print(i.name,i.psw)
run()
# 面向对象三大特性:封装、继承、多态
# 封装:将同一类方法封装到一个类中、将数据封装到对象中,将一些数据通过__init__初始化方法封装到对象中,以供日后使用
# 继承
# 示例一
class Father: # 父类
def func(self,a):
print(a)
class Son(Father): # 子类,继承父类中的方法
def show(self,b):
print(b)
s1 = Son()
s1.func(3) # 优先在自己类中找,找不到再到父类中找
s1.show(4)
# 示例二
class Base:
def f1(self):
print('Base.f1')
class Foo(Base):
def f2(self):
print('befor')
self.f1() # 调用f1方法,相当于obj.f1
print('foo.f2')
obj = Foo()
obj.f2() # 输出: befor Base.f1 foo.f2
# 示例三
class Base:
def f1(self):
print('Base.f1')
class Foo(Base):
def f2(self):
print('befor')
self.f1() # 调用f1方法,相当于obj.f1,f1在自己这里能找到,所以调用自身区域的f1
print('foo.f2')
def f1(self):
print('foo.f1')
obj = Foo()
obj.f2() # 输出: befor foo.f1 foo.f2
# 示例三
class Base:
def f1(self):
print('befor')
self.f2() # 调用f2方法,相当于obj.f2,因此调用的是Foo类里的f2
print('base.f2')
def f2(self):
print('Base.f1')
class Foo(Base):
def f2(self):
print('foo.f1')
obj = Foo()
obj.f1() # 输出: befor foo.f1 base.f2
# 示例三:多继承
class A1:
def f1(self):
print('A1.f1')
def f2(self):
print('A2.f2')
class B1:
def f1(self):
print('B1.f1')
def f3(self):
print('B1.f3')
class C1(A1,B1):
def f4(self):
print('C1.f4')
xxx = C1()
xxx.f1() # A1.f1 多继承情况下,优先继承左边的函数
# 示例四:多层次继承关系
class Base:
def f1(self):
print('Base.f1')
def f2(self):
print('Base.f2')
class Son1:
def f1(self):
print('Son1.f1')
def f2(self):
print('Son1.f2')
class Son2(Base):
def f1(self):
print('Son2.f1')
def f4(self):
print('Son2.f4')
class Children(Son2,Son1):
def f1(self):
print('Children.f1')
def f5(self):
print('Children.f5')
family = Children()
family.f2() # Base.f2
# 多态
class Email(object):
def send(self):
print('发邮件')
class Wechat(object):
def send(self):
print('发微信')
def func(arg):
v = arg.send()
v1 = Email()
func(v1) # 发邮件
v2 = Wechat()
func(v2) # 发微信
# 对象成员:变量(实例变量、类变量)、方法(绑定方法、类方法、静态方法)
class Person(object):
contry = '中国' # 类变量
def __init__(self,age,name):
self.age = age
self.name = name
def show(self):
message = '{}是{}人,今年{}岁'.format(self.name,Person.contry,self.age) # Person.contry也可以表示为self.contry
print(message)
p1 = Person(18,'Jack') # 实例变量
p1.show() # Jack是中国人,今年18岁
print(p1.age)
print(p1.name)
print(p1.contry)
p1.name = 'Lilei' # 将name重置为Lilei
p1.area = '浙江省' # 新增一个实例变量
p1.contry = 'Datang' # p1中新增一个实例变量
print(p1.contry) # Datang
print(Person.contry) # 中国
Person.contry = '美国' # 将类变量改成美国
print(Person.contry) # 美国
# 如果有继承关系,在自己找不到变量,则到父类中找
class Base(object):
contry = '元朝'
class Person(Base):
def __init__(self,age,name):
self.age = age
self.name = name
def show(self):
message = '{}是{}人,今年{}岁'.format(self.name,Person.contry,self.age) # Person.contry也可以表示为self.contry
print(message)
p2 = Person(22,'Jim')
Person.contry = '明朝' # 在Person类中新增contry = '明朝'
Base.contry = '秦朝' # 将Base类的contry改成秦朝
p2.contry = '汉朝' # 在p2中新增contry = '汉朝'
# 方法:绑定方法、类方法、静态方法,取决于你用到哪些参数
class Foo(object):
def __init__(self,name):
self.name = name
def f1(self):
print('绑定方法',self.name)
@classmethod # 类方法固定搭配
def f2(cls): # 默认有一个cls参数
print('类方法',cls)
@staticmethod # 静态方法固定搭配
def f3(): # 参数可以没有或者很多个
print('静态方法')
# 绑定方法调用
obj = Foo('张学友')
obj.f1()
# 类方法调用,cls就是这个方法的类
Foo.f2()
obj.f2()
# 静态方法调用
Foo.f3()
obj.f3()
# 属性:由绑定方法+装饰器组合,属性名和变量名不能重名,否则报错
class Aaa(object):
def __init__(self,name):
self.name = name
def f1(self):
return 123
@property
def f2(self):
return 333
obj = Aaa('xueyou')
v1 = obj.f1()
v2 = obj.f2 # 可以不用加括号
# 成员修饰符:公有、私有(用双下划线表示)
class Bbb(object):
def __init__(self,name,age):
self.__name = name # 私有变量
self.age = age # 公有变量
def f1(self):
return self.__name # 内部可以调用
def f2(self):
return self.age
obj = Bbb('学友',28)
# print(obj.__name) 会报错,无法调用
print(obj.age)
class Ccc(object):
def fff(self):
print('公有类方法')
def __fff(self):
print('私有类方法')
def ggg(self):
print('公有类方法')
self.__fff() # 内部可以调用
obj = Ccc()
obj.fff() # 可用
# obj.__fff() # 不可用
obj.ggg() # 间接调用私有类方法
obj._Ccc__fff() # 通过这种方式可以引用,不推荐用
# 父类的私有方法,子类无法继承
# 对象嵌套
# 案例
class Stars(object):
def __init__(self,name,trad):
self.name = name
self.trad = trad
def message(self):
data = '我叫{},是一个{},请大家多多关注'.format(self.name,self.trad)
return data
s1 = Stars('张学友','歌手')
s2 = Stars('李连杰','功夫演员')
s3 = Stars('巴特尔','篮球运动员')
class Guilei(object):
def __init__(self,nationality):
self.nationality = nationality
self.stars_list = []
def add_star(self,star):
self.stars_list.append(star)
def add_stars(self,stars):
for i in stars:
self.stars_list.append(i)
def show(self):
for item in self.stars_list:
print('我叫{},是一个{},我是{}人'.format(item.name,item.trad,self.nationality))
g1 = Guilei('中国')
g1.add_star(s1)
g1.add_stars([s2,s3])
for item in g1.stars_list:
print(item.message())
print(item.name,item.trad)
g1.show()
# >>>
# 我叫张学友,是一个歌手,请大家多多关注
# 张学友 歌手
# 我叫李连杰,是一个功夫演员,请大家多多关注
# 李连杰 功夫演员
# 我叫巴特尔,是一个篮球运动员,请大家多多关注
# 巴特尔 篮球运动员
# 我叫张学友,是一个歌手,我是中国人
# 我叫李连杰,是一个功夫演员,我是中国人
# 我叫巴特尔,是一个篮球运动员,我是中国人
# 特殊成员
# __init__、__new__
class Ddd(object):
def __init__(self,name):
print('第二步,初始化对象,在空对象中创建数据')
self.name = name
def __new__(cls, *args, **kwargs): # 用处不大
print('第一步,创建空对象,并返回')
return object.__new__(cls)
obj = Ddd('张学友')
# __call__:
class Eee(object):
def __call__(self, *args, **kwargs):
print('执行call方法')
obj = Eee()
obj() # 可以对象加括号执行call方法
#__str__ :展示用
class Fff(object):
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return '{},{}'.format(self.name,self.age) # 必须return一个字符串
s1 = Fff("张学友","28")
print(s1) #张学友,28 如果没有__str__,则输出的是一个内存地址
#__dict__:转换成字典
class Ggg(object):
def __init__(self,name,age):
self.name = name
self.age = age
s1 = Ggg("张学友","28")
print(s1.__dict__) # {'name': '张学友', 'age': '28'}
# __getitem__、__setitem__、__detitem__
class Hhh(object):
def __getitem__(self, item):
print(item)
def __setitem__(self, key, value):
print(key,value)
def __delitem__(self, key):
print(key)
obj = Hhh()
obj['xxx'] # xxx
obj['xxx'] = 123 # xxx 123
del obj['xxx'] # xxx
# __enter__、__exit__
class Iii(object):
def __enter__(self):
print('进来了')
return 'fff'
def __exit__(self, exc_type, exc_val, exc_tb):
print('出去了')
obj = Iii()
with obj as f: # f就是enter方法的返回值,也即fff
print('你好') # 进来了 你好 出去了
# __add__:相加,另外还有相乘相除等等,
class Jjj(object):
def __init__(self,name):
self.name = name
def __add__(self, other):
return '{}是{}的字'.format(self.name,other.name)
v1 = Jjj('子美')
v2 = Jjj('杜甫')
v3 = v1 + v2
# 对象+值,内部会执行对象__add__方法,并将加号后面的值当参数传递进去,也即self是v1,other是v2,v3是add的返回值
print(v3)
# 问题:只接受两个相加吗?