类的定义规则:
属性
方法
对象名 = 类名()
其实方法就是函数只不过在类中称为方法 ,方法是自动定义一个self的,因为你必须要定义一个参数来表示你所创建的对象的本身,其实这个参数不一定是self也可以是其他的任何参数 ,但是默认一般都为self
其实对象被创立之后也可以被当作一个参数给进行传参的:
把对象当作参数给进行传递:
#我们来测试测试能不能把一个类给当作一个参数传进另一个对象中 class Person(object):#创建一个Person类 role = 'person' #静态属性 def __init__(self, name, sex, hp, ad): self.name = name self.sex = sex self.hp = hp self.ad = ad def attack(self,d): d.hp -= self.ad print('{}攻击了{},{}掉了{}点血'.format(self.name, d.name, d.name, self.ad)) class Dog(object):#创建一个Dog类 def __init__(self, name, sex, hp, ad): self.name = name self.sex = sex self.hp = hp self.ad = ad def attack1(self, d): print('{}攻击了{},{}掉了{}点血'.format(self.name, d.name, d.name, self.ad)) d.hp -=self.ad #这一步就是调用了 传递进来的对象的参数 你把传递进来的对象的属性给调用了 alex = Person('老王', '男', 700, 40) #创建一个Person的对象 Agon = Dog('日天', '公', 30, 40)#创建一个Dog的对象 #我们可以试试把对象当作参数互相的传递 alex.attack(Agon) #用对象alex调用创建它的类中的方法然后把老张这个对象给传递进去 print(Agon.hp) Agon.attack1(alex) #把对象老张调用创建它的类中的方法 然后把alex这个对象当作一个参数给传递进去 print(alex.hp)
对象也是含有命名空间和作用域的:
类就是可以看成是一个总的模板 我们可以运用这个模板来加工很多的模具 虽然这些模具是都是这一个模板加工的 但是这些模具都是互相不相关的,
就是你可以用这个类创建很多的不通同的对象 但是这些的的对象在内存中开辟的空间都是不一样的,所以每一个对象是互不关联的,你对自己对象内部的属性进行改变是不会对其他的对象的属性有关联的
对象在创建的时候就会自动开辟一个对象的内存空间 这个内存空间内会存储一个指针 这个指针指向创建对象的类的内存空间, 然后就会访问类中的__init__方法然后这个init方法会把自己具有的属性返还给对象 然后对象会把这些属性存储在自己的内存空间内,
就好比Person类创建了alex对象 然后alex对象通过自带的指针访问了Person类 然后把类中的__init__方法中的属性给返还给alex这个对象
首先是通过建立对象的时候自动生成的指针来指向了 类 然后自动进入类中的init方法 然后进入其中把其中的属性拿过来 当作对象的属性
建立的对象的内存地址只存储对象的属性 而方法和静态属性存储在类的内存空间中是为了节省内存 让多个对象去共享类中的资源
类中的__init__方法中的属性不可以和方法名是相同的,因为你的对象调用的时候就会先调用的就是自己内存内的属性不是方法名
class Person(object): role = 'person' def __init__(self, name,sex,hp,ad): self.name = name self.sex = sex self.hp = hp self.ad = ad self . attack = 'hahah' def attack(self): print(111) alex = Person('sb', '不详', 1, 5) print(alex.attack) #查看对象中的属性 print(alex.__dict__) #查看alex对象中的所有属性 alex.attack() #这个时候是会报错的 因为你的attack在init方法中定义了 也就代表你的对象中的属性是可以找到这个属性的 你用对象去查找这个属性肯定是先进入对象的内存空间找到后就直接返回 但是这个时候你的 attack是对象的属性 那么你的对象去调用的只是自己的属性不是方法 就会不能使用()所以会报错
对象的内存空间李:只存储对象的属性 而不存储方法和静态属性
方法和静态属性都存储在类的内存空间内
为了节省内存空间,让多个对象去共享类中的资源
对象也是可以通过指针去寻找和调用类中的属性的,但是这个属性是不存在于对象中的内存空间的:
class Person: role = 'person' # 静态属性 def __init__(self,name,sex,hp,ad): self.name = name # 对象属性 属性 self.sex = sex self.hp = hp self.ad = ad self.attack = 'hahaha' def attack(self): print('%s发起了一次攻击'%self.name) alex = Person('a_sb','不详',1,5) boss_jin = Person('金老板','女',50,20) print(alex.role) #因为对象的内存空间中没有静态属性那么这一步是通过指针去类的空间中找到了 全局属性role alex.role = 'dog' #这一步并不是修改了静态属性 只是对象alex在自己的内存空间内创建了一个role属性 和全局属性并不是同一个
因为列表中的存储的 过程和java中的列表存储一样都是有一个栈和堆 然后还要一个指定的id来指向栈 所以我们可以运用两个小方法来表示他们的存储过程:
class Person(object): money = [0] def __init__(self, name): self.name = name def work(self): print(self.name,'工作赚了1000元RMB') self.money[0] += 1000 #这个你是用对象调用了类中的属性 然后这个属性对应的是列表 因为列表在内存中的存储是栈和堆 所以他们的改变只是 栈指向堆的引用改变了 但是你类查找栈的指向没变 所有你指向栈的值会一直随着栈指向堆的改变而改变 father = Person('father') mother = Person('mother') mother.work() father.work() print(Person.money) class Person: money = [0] def __init__(self,name): self.name = name def work(self): print(self.name,'工作,赚了1000块钱') self.money = [Person.money[0] + 1000] #如果是这种你就是把所有的值只是复制给对象的 因为你在用self的时候你不能直接使用静态属性money那么只能去类中查找 然后你这个时候先算右边的 你的右边的是Person.money[0]只是栈指向堆的引用值 你加上100 只是把这个引用值给 改变了 并没有把你类指向栈的引用给改变 那么你的值就不会改变 father = Person('father') mother = Person('mother') mother.work() father.work() print(Person.money)
下面是很重要的内存改变的过程:
很绕很绕:
class Person(object): money = 0 def __init__(self, name): self.name = name def work(self): #定义一个方法让家里人工作的钱都存在这里面 谁工作就增加1000元 print(self.name,'工作,赚了1000元') Person.money +=1000 #因为你是求你全部的钱数只能对类来调用 如果你用self来调用就是对象对它的调用了 只是求的每一个对象的钱数 mother = Person('mother') #创建了一个father对象 并把father这个参数传递进去 father = Person('father') #上面创建了两个对象 mother.work() father.work() #每调用一次就用对象执行一次 所以一共是两次 print(Person.money) #结果是2000 class Person(object): money = [0] def __init__(self, name): self.name = name def work(self): print(self.name,'工作赚了1000元RMB') self.money[0] += 1000 #这个你是用对象调用了类中的属性 然后这个属性对应的是列表 因为列表在内存中的存储是栈和堆 所以他们的改变只是 栈指向堆的引用改变了 但是你类查找栈的指向没变 所有你指向栈的值会一直随着栈指向堆的改变而改变 father = Person('father') mother = Person('mother') mother.work() father.work() print(Person.money) #结果是2000 class Person: money = [0] def __init__(self,name): self.name = name def work(self): print(self.name,'工作,赚了1000块钱') self.money = [Person.money[0] + 1000] #如果是这种你就是把所有的值只是复制给对象的 因为你在用self的时候你不能直接使用静态属性money那么只能去类中查找 然后你这个时候先算右边的 你的右边的是Person.money[0]只是栈指向堆的引用值 你加上100 只是把这个引用值给 改变了 并没有把你类指向栈的引用给改变 那么你的值就不会改变 father = Person('father') mother = Person('mother') mother.work() father.work() print(Person.money) #这个结果是0 class Person: money = [0] def __init__(self,name): self.name = name def work(self): print(self.name,'工作,赚了1000块钱') self.money[0] += 1000 father = Person('father') mother = Person('mother') mother.work() father.work() print(Person.money) # 2000 or 0? #这个结果是2000 class Person(object): money = [0] def __init__(self, name): self.name = name def work(self): print(self.name, '工作,赚了1000块钱') self.money = [Person.money[0]+1000] father = Person('father') mother = Person('mother') mother.work() father.work() print(Person.money) #结果就是0 因为你是self.money 就相当于把重新赋值的值给传递到对象中的内存空间内 没有给类 class Person(object): money = [0] def __init__(self, name): self.name = name def work(self): print(self.name, '工作,赚了1000块钱') Person.money = [Person.money[0]+1000] father = Person('father') mother = Person('mother') mother.work() father.work() print(Person.money) #结果就是2000 因为你是直接进行赋值而不是进行引用的改变的只不过把赋值给了类
下面的图是对上面的解释
小练习:
查看一个家庭中的总收入
class Person(object): money = 0 def __init__(self, name): self.name = name def work(self): #定义一个方法让家里人工作的钱都存在这里面 谁工作就增加1000元 print(self.name,'工作,赚了1000元') Person.money +=1000 #因为你是求你全部的钱数只能对类来调用 如果你用self来调用就是对象对它的调用了 只是求的每一个对象的钱数 mother = Person('mother') #创建了一个father对象 并把father这个参数传递进去 father = Person('father') #上面创建了两个对象 mother.work() father.work() #每调用一次就用对象执行一次 所以一共是两次 print(Person.money)
查看一个类创建了多少个对象:
class Foo(object): count = 0 def __init__(self):#因为你要查看一共建立了多少个对象,每建立一个对象就会从init方法中获取一次属性 所以只需要查看init方被调用多少次既可以了 Foo.count +=1 #一定要用类来执行你用self来执行就是单独的每一个对象不是总的 f1 = Foo() f2 = Foo() print(Foo.count)
来看两个小知识点:
转载于:https://www.cnblogs.com/zhaoyunlong/p/8798008.html