আমি কীভাবে একটি অবজেক্ট তৈরি করতে এবং এর সাথে গুণাবলী যুক্ত করতে পারি?


309

আমি পাইথনে একটি গতিশীল অবজেক্ট (অন্য কোনও বস্তুর অভ্যন্তরে) তৈরি করতে চাই এবং তারপরে এতে বৈশিষ্ট্য যুক্ত করতে চাই।

আমি চেষ্টা করেছিলাম:

obj = someobject
obj.a = object()
setattr(obj.a, 'somefield', 'somevalue')

কিন্তু এটি কার্যকর হয়নি।

কোন ধারনা?

সম্পাদনা:

আমি একটি forলুপ থেকে বৈশিষ্ট্যগুলি সেট করছি যা মানগুলির তালিকার মধ্য দিয়ে লুপ হয়

params = ['attr1', 'attr2', 'attr3']
obj = someobject
obj.a = object()

for p in params:
   obj.a.p # where p comes from for loop variable

উপরের উদাহরণে আমি পেতাম obj.a.attr1,obj.a.attr2 , obj.a.attr3

আমি setattrফাংশনটি ব্যবহার করেছি কারণ আমি কীভাবে করব তা জানতাম নাobj.a.NAMEfor লুপ থেকে ।

pউপরের উদাহরণে মানটির ভিত্তিতে আমি কীভাবে বৈশিষ্ট্যটি সেট করব ?


4
"কাজ করেননি" বলতে কী বোঝ? আমি ধরে নিয়েছি এটি একটি অ্যাট্রিবিউটআরর ব্যতিক্রম উত্থাপন করেছে, তাই না?
জোশ রাইট

1
হাঁ। 'অবজেক্ট' অবজেক্টটির কোনও 'গুণফল' নেই
জন

6
তুমি কেন এটা করছ? জেনেরিক "অবজেক্ট" এর কোনও আসল অর্থ নেই । আপনি যে জিনিসটি তৈরি করছেন তার অর্থ কী ? কেন এটি সঠিক শ্রেণি বা নেমটিপল নয়?
এস .লট

1
উদাহরণটি আমার পক্ষে ন্যূনতম এবং বিভ্রান্তিকর নয় বা আপনি কেবল কারও সাথে কেন কাজ করেন না a = object()এবং আপনার প্রয়োজন তা আমি কেবল দেখতে পাচ্ছি না obj.a = object()। আবার আমি উদাহরণটি সম্পর্কে বলছি, আপনার আসল কোডে কোনও বস্তুর অভ্যন্তরের কোনও উপাদান কার্যকর হতে পারে।
কন সাইক

উত্তর:


214

আপনি আমার প্রাচীন গুচ্ছ রেসিপিটি ব্যবহার করতে পারেন , তবে আপনি যদি "গুচ্ছ শ্রেণি" তৈরি করতে না চান তবে খুব সাধারণ একটি পাইথনে ইতিমধ্যে উপস্থিত রয়েছে - সমস্ত ফাংশনে স্বতন্ত্র বৈশিষ্ট্য থাকতে পারে (ল্যাম্বদা ফাংশন সহ)। সুতরাং, নিম্নলিখিত কাজ করে:

obj = someobject
obj.a = lambda: None
setattr(obj.a, 'somefield', 'somevalue')

সম্মানজনক Bunchরেসিপি তুলনায় স্বচ্ছতা হ্রাস ঠিক আছে কিনা, একটি স্টাইল সিদ্ধান্ত আমি অবশ্যই আপনার উপর ছেড়ে দেব।


25
@ ফোগলবার্ড, একটি স্টাইলের সিদ্ধান্ত, যেমনটি আমি উল্লেখ করেছি। কিছু সিএস বিশেষজ্ঞ যেমন চার্চের ল্যাম্বডা ক্যালকুলাসে প্রশিক্ষণপ্রাপ্ত (ল্যাম্বডাস) সমস্ত তথ্যের মৌলিক ধরণের হিসাবে বিবেচনা করতে ব্যবহৃত হয় (উদাহরণস্বরূপ, সংখ্যার ২৩, সমতুল্য হিসাবে দেখা যেতে পারে lambda: 23), সুতরাং lambdaএই উদ্দেশ্যে এটি ব্যবহার করে এমন বিশেষজ্ঞরা সম্ভবত "হ্যাক" এর মতো কিছুই অনুভব করবে না। ব্যক্তিগতভাবে, আমি lambda পাইথনে খুব বেশি পছন্দ করি না - তবে এটি ব্যক্তিগত স্বাদের একটি বিষয়।
অ্যালেক্স মার্টেলি

এবং কিছু ক্ষেত্রে, lambdaআপনার ব্যবহারের ক্ষেত্রে প্যাটার্নটি খাপ খায় কিনা তা বিবেচনা করে আপনি বুঝতে পারবেন যে আপনি যে তথ্যটিকে মূলত ডেটা হিসাবে ভেবেছিলেন তা আসলে কোনও ফাংশনের মতোই - বা কোনও ক্ষেত্রে কোনও ফান্টেক্টর।
কাইল স্ট্র্যান্ড

5
@ naught101, পাইথনে একটি ফাংশন হ'ল একটি অবজেক্ট, তাই আপনার আপত্তি আকাঙ্ক্ষিত।
অ্যালেক্স মার্টেলি

6
@ naught101, একটি নতুন ধরণের সৃষ্টি এড়ানো (বিদ্যমানটিকে পুনরায় ব্যবহার করা) জটিল করে তোলে না, এটি সহজ করে। আজকাল সম্ভবত বাস্তবে পছন্দ করা from argparse import Namespaceসত্ত্বেও আমার পছন্দ যদিও এটি অন্য কোথাও থাকতে পারে * যেমন, collection) - আবার একটি বিদ্যমান-বিদ্যমান টাইপটিকে পুনরায় ব্যবহার করা, আরও ভাল এবং এখনও নতুন ধরণের সৃষ্টি এড়ানো। কিন্তু, তখন সেখানে ছিল না :-)।
অ্যালেক্স মার্টেলি

1
প্রকার মডিউল থেকে সিম্পলনেমস্পেস সম্পর্কিত "জেএফ সেবাস্তিয়ান" থেকে উত্তরটি দেখুন। যদি পাইথনের আপনার সংস্করণ এটি সমর্থন করে তবে এটিই সেরা সমাধান (এবং সিম্পলনেমস্পেসের জন্য ঠিক কী নকশা করা হয়েছিল)
টিম রিচার্ডসন

333

অন্তর্নির্মিতটি objectতাত্ক্ষণিকভাবে চালু করা যেতে পারে তবে এতে কোনও বৈশিষ্ট্য সেট করা যায় না। (আমি আশা করি এটি এই নিখুঁত উদ্দেশ্যে করা সম্ভব __dict__হত )) বৈশিষ্ট্যগুলি ধরে রাখার এটির কোনও দরকার নেই ।

আমি সাধারণত এটি করি:

class Object(object):
    pass

a = Object()
a.somefield = somevalue

আমি যখন পারি, আমি দিই Object ক্লাসটিকে আরও অর্থপূর্ণ নাম দিয়ে থাকি, এটিতে আমি কী ধরণের ডেটা রাখছি তার উপর নির্ভর করে।

কিছু লোক একটি পৃথক কাজ করে, যেখানে তারা এর একটি উপ-শ্রেণীর ব্যবহার dictকরে যাতে কীগুলিতে অ্যাট্রিবিউট অ্যাক্সেসের অনুমতি দেয়। ( d.keyপরিবর্তে d['key'])

সম্পাদনা করুন : আপনার প্রশ্নের সংযোজনের জন্য, ব্যবহার setattrকরা ভাল। আপনি শুধু ব্যবহার করতে পারবেন না setattrউপর object()দৃষ্টান্ত।

params = ['attr1', 'attr2', 'attr3']
for p in params:
    setattr(obj.a, p, value)

9
এটি তাত্ক্ষণিকভাবে তৈরি করা যেতে পারে, এটি কার্যকর হয়ে গেলে কোনও কিছু কার্যকর করার জন্য ব্যবহৃত হয় না। foo = object()কাজ করে, তবে আপনি এটির সাথে খুব বেশি কিছু করতে পারবেন না
ড্যানিয়েল ডিপোলো

ওহে. উত্তরের জন্য ধন্যবাদ. আমি উপরে আমার সমস্যা আপডেট করেছি। সম্পাদনা দেখুন। আপনি কি এর উত্তর জানেন?
জন

দুঃখিত আমি এখনও এটি অবজেক্টে সেট করতে চাই। উপরে আপডেট দেখুন।
জন

আমি আপনার উত্তরটি সত্যিই পছন্দ করি এবং আমি মনে করি ভবিষ্যতে আমি এই দিকটি ঝুঁকিয়ে দেব। আমি খুব সাধারণ, বোধগম্য এবং পঠনযোগ্য পদ্ধতি ব্যতীত এই পোস্টে অন্য সমস্ত কিছু ব্যবহার করেছি। type....ল্যাবডা ব্যবহার বা ল্যাম্বডা কখনই আমার পছন্দ ছিল না, যেমন আমার কোডে পাঠ্য বমি হয়। তবে সম্পত্তিটি ধারণ করতে অবজেক্টগুলি ব্যবহার করার জন্য এই ধারণাটি দুর্দান্ত। লাম্বদা দেখলে কোডগুলি আরও পঠনযোগ্য বি / সি পাতা ছেড়ে দেয় আমি আপনার পাঠকে মোটামুটি বোধ করি যখন 25% করে রাখি! ধন্যবাদ।
মার্চ

দুর্দান্ত উত্তর, কেবলমাত্র আমি পরিবর্তন করেছি Structক্লাসের নাম হিসাবে এটি আরও স্পষ্ট করার জন্য ব্যবহার করা। আমাকে এক টন টাইপ করে বাঁচিয়েছে ["এবং "]চিয়ার্স!
pragman

137

নেই types.SimpleNamespaceপাইথন মধ্যে 3.3+ বর্গ :

obj = someobject
obj.a = SimpleNamespace()
for p in params:
    setattr(obj.a, p, value)
# obj.a.attr1

collections.namedtuple, typing.NamedTupleঅপরিবর্তনীয় বস্তুর জন্য ব্যবহার করা যেতে পারে। পিইপি 557 - ডেটা ক্লাসগুলি একটি পরিবর্তনীয় বিকল্পের পরামর্শ দেয়।

আরও উন্নত কার্যকারিতার জন্য, আপনি প্যাকেজ চেষ্টাattrs করতে পারেন । দেখুন একটি উদাহরণ ব্যবহার


3
আপনি এমন কিছু বিষয় যা পাইথন 2.7 সঙ্গে কাজ করে প্রয়োজন হলে, আপনার কাছে চেষ্টা করে দেখতে পারেন argparse.Namespaceবর্গ
RolKau

সম্মতি জানানো হয়েছে - এখানে কোনও নেতিবাচকতা থাকলে আমি কৌতূহলী হব, তবে এটি একটি অবিশ্বাস্যরূপে অজগর 3..৩++ পয়সা।
ghukill

অভিশাপ! এটি 2.7 এ পাওয়া যায় না?
রোল

@ রোল attrsপ্যাকেজটি পাইথন ২.7 সমর্থন করে
জেএফএস

এটি ইউনিটেস্ট.মকের চেয়ে আমার কাছে আরও ভাল সমাধান বলে মনে হচ্ছে; পরেরটি কিছুটা ভারী ওজন এবং কিছুটা মাতাল। মক অবজেক্টের সাহায্যে, কোনও গুণকে কেবল নির্ধারিত করার ফলে এটি অস্তিত্বের মধ্যে বসতে পারে; সিম্পলনেমস্পেস এটি প্রতিহত করবে।
jdzions

32

এই লক্ষ্যে পৌঁছানোর কয়েকটি উপায় রয়েছে। মূলত আপনার প্রয়োজন এমন একটি বস্তু যা প্রসারণযোগ্য।

obj.a = type('Test', (object,), {})  
obj.a.b = 'fun'  

obj.b = lambda:None

class Test:
  pass
obj.c = Test()

14
obj.a = type('', (), {})
ইমান

26

mockমডিউল মূলত যে জন্য তৈরি করা হয়।

import mock
obj = mock.Mock()
obj.a = 5

3
অসুবিধা হ'ল এটি একটি বাহ্যিক নির্ভরতা
কংগুর


2
আমি মনে করি আপনার কোড ব্যবহারের উপর নির্ভর করে। এটি যদি প্রোডাকশন কোড হয় তবে আমি এতে কিছু mockচাই না। আমার কাছে কেবল অদ্ভুত লাগছে।
মাইক ডি ক্লার্ক

21

এখন আপনি এটি করতে পারেন (এটি খারাপের মতো একই উত্তর কিনা তা নিশ্চিত নয়):

MyObject = type('MyObject', (object,), {})
obj = MyObject()
obj.value = 42

@ বৌপ্পির উত্তরটি সরাসরি মাইবজেক্টে (শ্রেণি) বৈশিষ্ট্যগুলি সেট করে, এর উদাহরণটি আপনার মতো নয়।
jfs

18

নীচের কোডটি ব্যবহার করে দেখুন:

$ python
>>> class Container(object):
...     pass 
...
>>> x = Container()
>>> x.a = 10
>>> x.b = 20
>>> x.banana = 100
>>> x.a, x.b, x.banana
(10, 20, 100)
>>> dir(x)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__',     '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'banana']

1
আপনি কি এটি আরও ব্যাখ্যা করতে পারেন? কোডটি এই সমস্যাটি সমাধানের জন্য কার্যকর হতে পারে, যদিও এটি ব্যাখ্যা করা কেবল একটি সমস্যার চেয়ে অনেক বেশি এগিয়ে যেতে পারে।
ডেডচেক্স

1
@ ডেড শেেক্স স্পষ্টতই এটি একটি নতুন শ্রেণি তৈরি করেছে (অবজেক্ট) যা অবজেক্ট বৈশিষ্ট্য সহ একটি খালি শ্রেণি, এবং শ্রেণীর ভিতরে বৈশিষ্ট্যগুলি সঞ্চয় করে। এটি আরও মডিউল ইনস্টল করার চেয়ে বেশি ভাল, বা ল্যাম্বডাসের উপর নির্ভর করে।
এম

2
নিশ্চিত না কেন এর আরও বেশি অগ্রগতি নেই Not এটি একটি বেসিক ধারক শ্রেণীর জন্য না ব্যবহার করার কোনও কারণ আছে কি? পাইথন 2.7, 2.6, এবং 3.4
ইউজার 5359531

17

আপনি সরাসরি কোনও শ্রেণীর বস্তুও ব্যবহার করতে পারেন; এটি একটি নেমস্পেস তৈরি করে:

class a: pass
a.somefield1 = 'somevalue1'
setattr(a, 'somefield2', 'somevalue2')

9

যেমন ডকস বলেছেন :

নোট : objectনেই না একটি আছে __dict__তাই আপনি যা করতে পারেন না একটি দৃষ্টান্ত নির্ধারিত নির্বিচারে গুণাবলীর objectবর্গ।

আপনি কেবল ডামি-ক্লাসের উদাহরণ ব্যবহার করতে পারেন।


2

এই সমাধানগুলি পরীক্ষার সময় খুব সহায়ক। প্রত্যেকের উত্তরের উপর ভিত্তি করে আমি পাইথন ২.7.৯ এ এটি করি (স্ট্যাটিকমেডো ছাড়াই আমি একটি টাইপ-এরর পেয়েছি (আনবাউন্ড পদ্ধতি ...):

In [11]: auth = type('', (), {})
In [12]: auth.func = staticmethod(lambda i: i * 2)
In [13]: auth.func(2)
Out[13]: 4

1

আপনি কোন জিনিস ব্যবহার করছেন? একটি নমুনা শ্রেণীর সাহায্যে এটি চেষ্টা করে দেখুন এবং এটি দুর্দান্ত কাজ করেছে:

class MyClass:
  i = 123456
  def f(self):
    return "hello world"

b = MyClass()
b.c = MyClass()
setattr(b.c, 'test', 123)
b.c.test

এবং আমি পেয়েছি 123 উত্তর হিসাবে ।

আপনি যদি চেষ্টা করে থাকেন তবে একমাত্র পরিস্থিতি যেখানে আমি ব্যর্থ see setattr কোনও বিল্টিন অবজেক্টে ।

আপডেট: মন্তব্য থেকে এটি একটি পুনরাবৃত্তি: আপনি পাইথনে বস্তুর জন্য বৈশিষ্ট্যগুলি যুক্ত করতে পারেন না কেন?


বিসি আপত্তি সেট করা হয়েছে () একটি সংজ্ঞায়িত শ্রেণি নয়
জন

0

দিনের শেষ দিকে এদিকে আসছি তবে এখানে আমার পেনিওয়ার্থ এমন একটি অবজেক্টের সাথে রয়েছে যা কেবলমাত্র একটি অ্যাপে কিছু দরকারী পাথ ধরে রাখে তবে আপনি যে কোনও তথ্যের জন্য একটি সর্দা ডিক চান যেখানে আপনি গিটট্রা এবং ডট স্বরলিপি সহ অ্যাক্সেস করতে পারেন এমন কোনও কিছুর জন্য আপনি এটি খাপ খাইয়ে নিতে পারেন you (যা আমি এই প্রশ্নটি সম্পর্কে সত্যিই মনে করি):

import os

def x_path(path_name):
    return getattr(x_path, path_name)

x_path.root = '/home/x'
for name in ['repository', 'caches', 'projects']:
    setattr(x_path, name, os.path.join(x_path.root, name))

এটি দুর্দান্ত কারণ এখন:

In [1]: x_path.projects
Out[1]: '/home/x/projects'

In [2]: x_path('caches')
Out[2]: '/home/x/caches'

এই ব্যবহার করে, তাই উপরে উত্তর কিন্তু মত ফাংশন বস্তুর মান (আপনি এখনও ব্যবহার করতে পারেন পেতে ফাংশন ব্যবহার (getattr, x_path, 'repository')বদলে x_path('repository')যদি আপনি পছন্দ)।


0

যদি আমরা নেস্টেড অবজেক্ট তৈরির আগে সমস্ত বৈশিষ্ট্য এবং মান একসাথে নির্ধারণ করতে এবং একত্রিত করতে পারি, তবে আমরা একটি নতুন শ্রেণি তৈরি করতে পারি যা সৃষ্টির উপর একটি অভিধানের যুক্তি নিয়ে থাকে।

# python 2.7

class NestedObject():
    def __init__(self, initial_attrs):
        for key in initial_attrs:
            setattr(self, key, initial_attrs[key])

obj = someobject
attributes = { 'attr1': 'val1', 'attr2': 'val2', 'attr3': 'val3' }
obj.a = NestedObject(attributes)
>>> obj.a.attr1
'val1'
>>> obj.a.attr2
'val2'
>>> obj.a.attr3
'val3'

আমরা কীওয়ার্ড আর্গুমেন্টের অনুমতি দিতে পারি। এই পোস্টটি দেখুন ।

class NestedObject(object):
    def __init__(self, *initial_attrs, **kwargs):
        for dictionary in initial_attrs:
            for key in dictionary:
                setattr(self, key, dictionary[key])
        for key in kwargs:
            setattr(self, key, kwargs[key])


obj.a = NestedObject(attr1='val1', attr2='val2', attr3= 'val3')

-2
di = {}
for x in range(20):
    name = '_id%s' % x
    di[name] = type(name, (object), {})
    setattr(di[name], "attr", "value")

-2

অন্যভাবে আমি এইভাবে দেখছি:

import maya.cmds

def getData(objets=None, attrs=None):
    di = {}
    for obj in objets:
        name = str(obj)
        di[name]=[]
        for at in attrs:
            di[name].append(cmds.getAttr(name+'.'+at)[0])
    return di

acns=cmds.ls('L_vest_*_',type='aimConstraint')
attrs=['offset','aimVector','upVector','worldUpVector']

getData(acns,attrs)

আপনি ([এ cmds.getAttr (নাম + এ) [0] '।']) এই দ্বি [NAME] .append ATTR নাম পরিশেষে যোগ জুড়তে পারেন
পাবলো এমানুয়েল ডি লিও

1
এটি একটি খুব বড় অ-মানক নির্ভরতা যুক্ত করছে যখন একটি সাধারণ class a: passসমস্ত প্রয়োজনীয় শক্তি দেয়।
অ্যালেক্সিস পাকস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.