方法和函数区分

fun及Foo.display为函数,obj.display为方法,类实例化后,之前的函数就变成了方法

def fun():
pass
print(fun)

class Foo(object):
def display(self):
pass

print(Foo.display)

obj = Foo()
print(obj.display)
<function fun at 0x0000028F1303D268>
<function Foo.display at 0x0000028F160B48C8>
<bound method Foo.display of <__main__.Foo object at 0x0000028F133ABAC8>>

写一个函数来区分对象

from types import MethodType,FunctionType

def check(args):
if isinstance(args,MethodType):
print('这是方法')

elif isinstance(args,FunctionType):
print('这是函数')

else:
print('这是啥')
check(fun)
check(obj.display)
这是函数
这是方法

小练习

class RoleConfig(object):
def f1(self,args):
print('f1',args)

def f2(self,args):
print('f2',args)

def f3(self,args):
print('f3',args)

list_display = [f1,f2]

def get_list_display(self):
self.list_display.insert(0,obj.f3)
return self.list_display


obj = RoleConfig()
for item in obj.get_list_display():
item(obj,2)

报错是因为obj中此时的f3为方法,而f1、f2为函数

Traceback (most recent call last):
File "D:/Practise/project01/app02/test/20220110.py", line 21, in <module>
item(obj,2)
TypeError: f3() takes 2 positional arguments but 3 were given

单例模式

编辑三个模块

test1

class AdminSite(object):
pass

obj1 = AdminSite()

test2

import test1

print(test1.obj1)

import test3

test3

import test1
print(test1.obj1)

执行test2,显示内存地址相同,程序没有重复执行,是直接调用

<test1.AdminSite object at 0x000002CD41700FD0>
<test1.AdminSite object at 0x000002CD41700FD0>

想要使用单例模式,就像test1那样,直接在模块中实例化,其他模块使用时直接调用即可。

静态方法(类变量)

class RoleConfig(object):
def f1(self,args):
print('f1',args)

def f2(self,args):
print('f2',args)

def f3(self,args):
print('f3',args)

list_display = [f1,f2]

def get_list_display(self):
self.list_display.insert(0,RoleConfig.f3)
return self.list_display


obj = RoleConfig()
for item in obj.get_list_display():
item(obj,2)
obj1 = RoleConfig()
for item in obj1.get_list_display():
item(obj1,2)

打印结果为7行数据,第一次执行get_list_display(),list_display列表更新为[f1,f2,f3]

f3 2
f1 2
f2 2
f3 2
f3 2
f1 2
f2 2

解决办法

class RoleConfig(object):
def f1(self,args):
print('f1',args)

def f2(self,args):
print('f2',args)

def f3(self,args):
print('f3',args)

list_display = [f1,f2]

def get_list_display(self):
v = []
v.extend(self.list_display) #不要用v=list_display,否则效果跟之前一样
v.insert(0,RoleConfig.f3)
return v


obj = RoleConfig()
for item in obj.get_list_display():
item(obj,2)
obj1 = RoleConfig()
for item in obj1.get_list_display():
item(obj1,6)

这次就是六个结果了

f3 2
f1 2
f2 2
f3 6
f1 6
f2 6

Python三大器

生成器

迭代器

通过yield可以降低内存消耗

def func(request):
result = []
data_list = models.Users.objects.all()
for row in data_list:
temp = "%s%s" (row.name,row.pwd,)
result.append(temp)
return render(request,'xxx.html',{'result':result})

通过yield优化

def get_result(data_list):
for row in data_list:
temp = "%s%s" (row.name,row.pwd)
yield temp

def func(request):
data_list = models.Users.objects.all()
return = get_result(data_list)
return render(request,'xxx.html',{'result':result})


xxx.html

{% for row in result %}
{{row}}
{% endfor %}

可迭代对象

class Row(object):
def __init__(self,data):
self.data = data

def __iter__(self):
yield "<div>"
yield '全部'
for item in self.data:
yield "<a href='/index/?p1=1.0'>%s</a>" %item
yield "</div>"
data_list = [
Row(['1.0以下','1.1-1.6']),
Row(['汽油','柴油','混合动力','电动']),
]

for row in data_list:
for field in row:
print(field)

封装

##################################老封装思想,后期没有修改变更可以使用
list_filter = [
{'text':'董方方','gender':'男','color':'xx'},
{'text':'黄晓雪','gender':'男','color':'xx'},
{'text':'李贝贝','gender':'男','color':'xx'},
]
for item in list_filter:
print(item['text']+item['gender'])


###################################新封装思想,后期如果还有变化,可以使用这个方法,两种方式按需采用
class Option(object):
def __init__(self,text,gender,color):
self.text = text
self.gender = gender
self.color = color
def get_t_g(self):
return self.text+self.gender

list_filter = [
Option(text='董方方',gender='男',color='xx'),
Option(text='黄晓雪',gender='男',color='xx'),
Option(text='李贝贝',gender='男',color='xx'),
]

for item in list_filter:
print(item.get_t_g())

装饰器

functools

def wrapper(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
@wrapper
def f1():
print('f1')
@wrapper
def f2():
print('f2')

print(f1.__name__)
print(f2.__name__)

结果

inner
inner

有functools

import functools

def wrapper(func):
@functools.wraps(func)
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
@wrapper
def f1():
print('f1')
@wrapper
def f2():
print('f2')

print(f1.__name__)
print(f2.__name__)

结果

f1
f2

闭包

闭包
def f1(a1,a2):
def inner():
ret = a1 + a2
return ret
return inner

n1 = f1('test','test1') #内存 a1='test',a2='test1'
n2 = f1('test1','test2') #内存 a1='test1',a2='test2'
n3 = f1('test3','test4') #内存 a1='test3',a2='test4'

n1()

# 帮助开发作者维护一个"私密"空间,用于为以后执行提供数据。

反射

getattr

from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.

def test(request):
from app01 import models
header_list = []
list_display=['id','username','phone']
for name in list_display:
header_list.append(models.UserInfo._meta.get_field(name).verbose_name)
print(header_list)
user_queryset = models.UserInfo.objects.all()
for item in user_queryset:
row = []
for field in list_display:
v = getattr(item,field)
row.append(v)
print(row)

return HttpResponse('test')

结果

['ID', '姓名', '手机号']
[1, 'name1', 1234]
[2, 'name2', 1234]
[3, 'name3', 1234]

常用

isinstance

判断对象是否为函数

from types import FunctionType
if isinstance(name_or_func,FunctionType):
val = name_or_func(self,item,False)
else:
val = getattr(item, name_or_func)
row.append(val)

Django

mark_safe

返回html到页面

from django.utils.safestring import mark_safe
from .models import Role,Dpet
class RoleConfig(StarkConfig):
def f1(self,row=None,header=False):
if header:
return '选择'
return mark_safe('<input type="checkbox" name="pk" value="%s" />' %row.pk)
list_display = [f1, 'id', 'title']

reverse

from django.urls import reverse

def display_edit(self, row=None, header=False):
if header:
return '编辑'
app_label = self.model_class._meta.app_label
model_name = self.model_class._meta.model_name
namespace = self.site.namespace
name = '%s:%s_%s_change'%(namespace,app_label,model_name)
url = reverse(name,kwargs={'pk':row.pk})
return mark_safe('<a href="%s"><i class="fa fa-edit" aria-hidden="true"></i></a>'%url)

ModelForm

def add_view(self, request):
'''
所有添加页面,都在此函数处理
使用ModelForm实现
:param request:
:return:
'''
class AddModelForm(forms.ModelForm):
class Meta:
model = self.model_class
fields = "__all__"

if request.method == "GET":
form = AddModelForm()
return render(request, 'stark/change.html', {'form': form})
form = AddModelForm(request.POST)
if form.is_valid():
form.save()
redirect(self.reverse_list_url())
return render(request, 'stark/change.html', {'form': form})

<h1>添加页面</h1>
<div style="width: 680px;margin:0 auto">
<form class="change" method="post">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label>{{ field.label }}</label>
{{ field }}
{{ field.errors.0 }}
</div>
{% endfor %}
<button type="submit" class="btn btn-default">提交</button>
</form>
</div>

获取FK/M2M/O2O对应的表中所有的数据

class UserInfo(models.Model):
title = models.CharField(verbose_name='标题',max_length=32)

def __str__(self):
return self.title

class Depart(models.Model):
name = models.CharField(verbose_name='部门名称',max_length=32)
tel = models.CharField(verbose_name='联系电话',max_length=32)
user = models.ForeignKey(verbose_name='负责人',to='UserInfo',on_delete=models.CASCADE)

def __str__(self):
return self.name
######fk_obj.rel.model.objects.all()中rel已不能使用,修改为remote_field
def get_fk_queryset(request):
from app02 import models
fk_obj = models.Depart._meta.get_field("user")
user_info_queryset = fk_obj.remote_field.model.objects.all()
print(user_info_queryset)
return HttpResponse('...')

Q对象

models.User.object.filter(name__containsj='李')
models.User.object.filter(name__contains='李',email__contains='李')

构造 or
con = Q()
con.children.append(('name__contains','李'))
con.children.append(('email__contains','李'))
models.User.object.filter(name__contains='李',email__contains='李')

c1 = Q()
c1.connector = 'OR'
c1.children.append(('name__contains','李'))
c1.children.append(('email__contains','李'))

c2 = Q()
c2.connector = 'AND'
c2.children.append(('id__gt',2))
c2.children.append(('age__lte',5))

c3 = Q()
c2.connector = 'AND'

c3.add(c1,'AND')
c3.add(c2,'AND')

(name=li or email=li) AND (id>2 and age<=5)

models.User.object.filter(con)

get_字段_display()

gender_choices = ((1, '男'), (2, '女'))
gender = models.IntegerField(verbose_name='性别', choices=gender_choices)
获取性别的名称而不是序号

get_gender_display()