对象拷贝,对象取值
Posted 相信美好的事情即将发生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对象拷贝,对象取值相关的知识,希望对你有一定的参考价值。
利用反射写的对象拷贝,取值:
- 支持区分大小写
- 对象直接取值
- 效率高
- 简单好用,不需要类似mapper配置
public static class ObjectUtils
/// <summary>
/// 获取实体的属性值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="model">实体对象</param>
/// <param name="propName">属性名称,忽略大小写</param>
/// <returns></returns>
public static object FetchValue<T>(this T model, string propName) where T : class, new()
var flag = BindingFlags.IgnoreCase;
return typeof(T).GetProperty(propName, flag)!.GetValue(model)!;
/// <summary>
/// 对象间拷贝
/// </summary>
/// <typeparam name="TSource">复制实体</typeparam>
/// <typeparam name="TDest">目标实体</typeparam>
/// <param name="sourceInstance">复制源数据</param>
/// <param name="targetInstance">目标源数据</param>
/// <param name="ignoreProperty">忽略字段</param>
public static void CopyTo<TSource, TDest>(this TSource sourceInstance, TDest targetInstance,
params object[] ignoreProperty)
where TSource : class
where TDest : class
var sourceType = typeof(TSource);
var targetType = typeof(TDest);
var targetProps = targetType.GetProperties().ToList();
foreach (var item in targetProps)
if (item.CanWrite)
var sourceProp = sourceType.GetProperty(item.Name);
if (null != sourceProp && sourceProp.CanRead && !ignoreProperty.Contains(item.Name))
targetType.SetPropertyValue(targetInstance, item.Name, sourceProp.GetValue(sourceInstance));
/// <summary>
/// 设置对象的属性值
/// </summary>
/// <param name="target"></param>
/// <param name="instance"></param>
/// <param name="name"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool SetPropertyValue(this Type target, object instance, string name, object value)
var p = target.GetProperty(name);
var v = p.PropertyType.GetFieldValue(value);
if (p != null && p.CanWrite)
p.SetValue(instance, v);
return true;
return false;
public static object GetFieldValue(this Type propType, object fieldValue)
if (Convert.IsDBNull(fieldValue) || fieldValue == null) return null;
if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(Nullable<>))
if (fieldValue != null)
var nullableConverter = new NullableConverter(propType);
propType = nullableConverter.UnderlyingType;
else
return propType.TypeInitializer;
return Convert.ChangeType(fieldValue, propType);
Python对象的拷贝
参考技术APython赋值操作或函数参数传递,传递的永远是对象引用(即内存地址),而不是对象内容。在Python中一切皆对象,对象又分为可变(mutable)和不可变(immutable)两种类型。对象拷贝是指在内存中创建新的对象,产生新的内存地址。当顶层对象和它的子元素对象全都是immutable不可变对象时,不存在被拷贝,因为没有产生新对象。浅拷贝(Shallow Copy),拷贝顶层对象,但不会拷贝内部的子元素对象。深拷贝(Deep Copy),递归拷贝顶层对象,以及它内部的子元素对象。
Python中一切皆对象,对象就像一个塑料盒子, 里面装的是数据。对象有不同类型,例如布尔型和整型,类型决定了可以对它进行的操作。现实生活中的"陶器"会暗含一些信息(例如它可能很重且易碎,注意不要掉到地上)。
对象的类型还决定了它装着的数据是允许被修改的变量(可变的mutable)还是不可被修改的常量(不可变的immutable)。你可以把不可变对象想象成一个透明但封闭的盒子:你可以看到里面装的数据,但是无法改变它。类似地,可变对象就像一个开着口的盒子,你不仅可以看到里面的数据,还可以拿出来修改它,但你无法改变这个盒子本身,即你无法改变对象的类型。
对象拷贝是指在内存中创建新的对象,产生新的内存地址。
浅拷贝(Shallow Copy),拷贝顶层对象,但不会拷贝内部的子元素对象。
2.1.1. 顶层是mutable,子元素全是immutable
当顶层对象是mutable可变对象,但是它的子元素对象全都是immutable不可变对象时,如[1, \'world\', 2]
① 创建列表对象并赋值给变量a
② 导入copy模块,使用copy.copy()函数浅拷贝a,并赋值给变量b
③ 修改变量a的子元素a[0] = 3,由于整数是不可变对象,所以并不是修改1变为3,而是更改a[0]指向对象3
当顶层对象是 mutable可变对象 ,但子元素也存在 mutable可变对象 时,如 [1, 2, [\'hello\',\'world\']]
① 浅拷贝 copy.copy() 只拷贝了顶层对象,没有拷贝子元素对象[\'hello\',\'world\'],即a[2]和b[2]指向同一个列表对象
② 修改a[2][1] = \'china\',则b[2][1] = \'china\'
当顶层对象是immutable不可变对象,同时它的子元素对象也全都是immutable不可变对象时,如(1, 2, 3)
变量a与变量b指向的是同一个元组对象,没有拷贝
当顶层对象是immutable不可变对象时,但子元素存在mutable可变对象时,如(1, 2, [\'hello\',\'world\'])
变量a与变量b指向的是相同的元组对象,并且a[2]与b[2]指向同一个列表,所以修改a[2][1]会影响b[2][1]
深拷贝(Deep Copy),递归拷贝顶层对象,以及它内部的子元素对象
当顶层对象是mutable可变对象,但是它的子元素对象全都是immutable不可变对象时,如[1, \'world\', 2]
变量a与变量b指向不同的列表对象,修改a[0]只是将列表a的第一个元素重新指向新对象,不会影响b[0]
当顶层对象是mutable可变对象,但子元素也存在mutable可变对象时,如[1, 2, [\'hello\',\'world\']]
深拷贝既拷贝了顶层对象,又递归拷贝了子元素对象,所以a[2]与b[2]指向了两个不同的列表对象(但是列表对象的子元素初始指定的字符串对象一样),修改a[2][1] = \'china\'后,它重新指向了新的字符串对象(内存地址为140531581905808),不会影响到b[2][1]
当顶层对象是immutable不可变对象,同时它的子元素对象也全都是immutable不可变对象时,如(1, 2, 3)
变量a与变量b指向的是同一个元组对象,不存在拷贝
当顶层对象是immutable不可变对象时,但子元素存在mutable可变对象时,如(1, 2, [\'hello\',\'world\'])
变量a与变量b指向的是不同的元组对象,同时a[2]与b[2]指向不同的列表对象,所以修改a[2][1]不会影响b[2][1]
使用=是赋值,即将列表对象的引用也赋值给变量b,可以将列表对象想像成一个盒子,变量a相当于这个盒子上的标签,执行b = a后,相当于再在这个盒子上贴上b标签,a和b实际上指向的是同一个对象。因此,无论我们是通过a还是通过b来修改列表的内容,其结果都会作用于双方。
b/c/d都是a的复制,它们都指向了不同的列表对象,但是没有拷贝子元素,a[2]和b[2]/c[2]/d[2]指向同一个列表, 相当于浅拷贝的效果
使用分片[:]操作,a和b其实是指向同一个元组,而且没有拷贝子元素,a[2]和b[2]也指向同一个列表,相当于浅拷贝的效果
同列表类似,可以使用字典的copy()函数或者转换函数dict()
变量a与变量b/c指向不同的字典,但是没有拷贝子元素,a[\'jobs\']和b[\'jobs\']/c[\'jobs\']指定同一个列表, 相当于浅拷贝的效果
同列表类似,可以使用集合的copy()函数或者转换函数set()
变量a与变量b/c指向不同的集合,而集合的元素必须是hashable,所以修改集合a不会影响到b/c
以上是关于对象拷贝,对象取值的主要内容,如果未能解决你的问题,请参考以下文章