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))
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()
类属性
使用同一类创建不同的对象
- 若没有改变过类属性,可以通过类属性改变,来改变对象中对应类属性的值。一起改变
- 若某一对象更改了类属性的值,则建立动态对象绑定,此对象中类属性变为修改后的数值;其他对象的类属性不变
- 再次改变类属性,已经动态绑定的对象,其对象的类属性不会受到影响;对于没有“私自”更改类属性的对象,其对应的类属性仍然会受到影响
对象属性
对象属性是依据类创建对象的时候,每个对象都具有的公共属性
其数值的更改需要通过调用对象属性赋值来修改,不能通过类属性更改
总结
类属性,不允许对象私自修改,有类统一修改,影响所有对象
对象属性,依据对象的特点,可以自己做出特定的修改。类没有权限去修改对象属性
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
- 不需要任何参数,但是也可以添加外部参数
# __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
即想达到对象属性私有化的目的
又想通过 对象.属性 的方法来调用和修改私有化后的属性
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
是一种继承关系
A is a B B是A的基类(父类)
可以产生代码上的重用性
比如:兔子 is 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,则从父类继承
子类继承父类,但是也需要自己定义
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))
父类中私有的属性,子类是无法继承的
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 小类型
即不能分辨接受对象所属的类型,所有类型的对象都可以接受
但是可以通过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