Как получить доступ к данным, хранящимся в этом объекте?

Я использую модуль BioPerl для получения строки из набора параметров. Я следил за страницей HOWTO:Beginners. Модуль, по-видимому, возвращает хэш-объект. Как получить фактическую строку из хеш-объекта?

use Bio::DB::GenBank;
use Data::Dumper;

my $gb = Bio::DB::GenBank->new(-format     => 'Fasta',
                             -seq_start  => 1,
                             -seq_stop   => 251,
                             -strand     => 1
                             -complexity => 1);
my $seq = $gb->get_Seq_by_acc('NG_016346');
my $sequence_string = lc($seq->seq());
my $seq_obj = Bio::Seq->new(-seq => $sequence_string,
                          -alphabet => 'dna' );
my $prot_obj = $seq_obj->translate;
print Dumper($prot_obj);

Дампер данных печатает следующее:

$VAR1 = bless( {
             'primary_seq' => bless( {
                                       'length' => 83,
                                       '_root_verbose' => 0,
                                       '_nowarnonempty' => undef,
                                       'seq' => 'RLCVKEGPWPAVEGTWSWG*HRPGSRACPRWGAPNSVQATSYTPSPTHAPFSVSPIPIC*MSLLEASCWPGSREDGARMSAGM',
                                       'alphabet' => 'protein'
                                     }, 'Bio::PrimarySeq' ),
             '_root_verbose' => 0
           }, 'Bio::Seq' );

Как мне получить 'seq', который хранится в $prot_obj?

Я старался

print $prot_obj{'primary_seq'}{'seq'};

но ничего не печатает. Дампер данных напечатал слово bless. Возможно, seq является полем объектно-ориентированной переменной.


person cooldood3490    schedule 27.10.2015    source источник


Ответы (3)


Правильный формат для доступа к свойствам объекта использует ->:

print $prot_obj->{'primary_seq'}->{'seq'};
person doublesharp    schedule 27.10.2015
comment
Требуется только первый ->. Использование -> после каждого {} (hashref), [] (arrayref) является старым синтаксисом. - person Eugen Konkov; 28.10.2015
comment
Это не обязательно старый синтаксис, просто perl знает, что все, что вложено в ref, должно быть другим ref, и, поскольку не может быть двусмысленности, последние операции разыменования не требуются. - person stevieb; 28.10.2015
comment
Боюсь, я не уверен, что это правильно. Суть объектно-ориентированного программирования заключается в инкапсуляции, поэтому прямое обращение к атрибутам вложенных объектов является дурным тоном. - person Sobrique; 28.10.2015
comment
Я определенно согласен с @Sobrique. Я мельком посмотрел на модуль, но не нашел аксессуар за то время, которое у меня было. - person stevieb; 28.10.2015
comment
FWIW, похоже, это документы для объекта Sequence: bioperl.org/wiki/HOWTO :Beginners#The_Sequence_Object. Например, чтобы получить или извлечь значение $sequence_as_string = $seq_obj->seq; - person doublesharp; 28.10.2015

Я собираюсь оспорить другой ответ и сказать, что правильный способ доступа к свойствам объекта - это не делать это, а вместо этого использовать метод.

Причина для этого - весь смысл ОО. Это инкапсуляция фрагментов вашей программы, чтобы несколько разработчиков могли работать с ней одновременно, а код масштабировался, потому что вы могли легче найти, где что-то идет не так.

Это работает, только если вы использовали опубликованные методы — указанный способ управления объектом — потому что тогда вам не нужно знать, что происходит за кулисами. Это также означает, что разработчик может свободно изменять то, что происходит — может быть, просто проверяя, но, возможно, перегружая или получая разные ответы в зависимости от другого свойства внутри объекта.

Все это ниспровергается прямым доступом к свойствам объекта.

Вы не должны этого делать, даже если perl "позволит" вам. Посмотрим правде в глаза, perl позволит вам делать много плохих вещей.

Bio::PrimarySeq имеет вызов метода seq. чтобы получить атрибут seq(). Bio::Seq имеет метод доступа к основной последовательности:

So:

$prot_obj -> seq(); 

Я думаю, наверное, сделал бы это. (Хотя документ не совсем легко читать).

person Sobrique    schedule 27.10.2015

Существует принятый ответ, но я бы также посоветовал не ковыряться в интервалах таких объектов, за исключением того, что нужно посмотреть, какой объект возвращается (или просто использовать ref). Вот как бы я подошел к проблеме:

use 5.010;
use strict;
use warnings;
use Bio::DB::GenBank;
use Bio::Seq;

my $gb = Bio::DB::GenBank->new(
    -format     => 'Fasta',
    -seq_start  => 1,
    -seq_stop   => 251,
    -strand     => 1,
    -complexity => 1
);

my $seq = $gb->get_Seq_by_acc('NG_016346');
my $seq_obj = Bio::Seq->new(
    -id       => $seq->id,
    -seq      => $seq->seq,
    -alphabet => 'dna' 
);

say join "\n", ">".$seq_obj->id, $seq_obj->translate->seq;

Запустив это, вы получите переведенную запись FASTA:

>gi|283837914:1-251
RLCVKEGPWPAVEGTWSWG*HRPGSRACPRWGAPNSVQATSYTPSPTHAPFSVSPIPIC*MSLLEASCWPGSREDGARMSAGM

Настоящая польза от использования BioPerl заключается в объединении различных классов для решения проблем с минимальным (но также читаемым и повторно используемым) кодом. В вашем коде также была небольшая опечатка, которая была бы обнаружена с включенными прагмами strict и warnings (это мой лучший совет).

person SES    schedule 28.10.2015